home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / dtime / data.1 / Datetime.cpp < prev    next >
C/C++ Source or Header  |  1996-07-08  |  91KB  |  3,782 lines

  1. /*
  2. Module : DATETIME.H
  3. Purpose: Implementation for a number of Date / Time classes
  4. Created: PJN / DATE/1 / 05-05-1995
  5. History: None
  6.  
  7. Copyright (c) 1995 by PJ Naughter.  
  8. All rights reserved.
  9.  
  10. */
  11.  
  12. /////////////////////////////////  Includes  //////////////////////////////////
  13. #include "stdafx.h"
  14. #include "limits.h"
  15. #include "time.h"
  16. #include "stdlib.h"
  17. #include "math.h"                                      
  18. #include "float.h"
  19. #include "win32sup.h"
  20. #include "datetime.h"
  21. #include "resource.h"
  22.  
  23.  
  24.  
  25. //////////////////////////////////  Macros  ///////////////////////////////////
  26. IMPLEMENT_SERIAL(CDate, CObject, 1)
  27. IMPLEMENT_SERIAL(CLTimeSpan, CObject, 1)
  28. IMPLEMENT_SERIAL(CLTimeOfDay, CObject, 1)
  29. IMPLEMENT_SERIAL(CLDate, CObject, 1)
  30.  
  31.  
  32.  
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char BASED_CODE THIS_FILE[] = __FILE__;
  36. #define new DEBUG_NEW
  37. #endif
  38.  
  39.  
  40. ////////////////////////////////// Locals /////////////////////////////////////
  41. LONG lfloor(LONG a, LONG b);
  42. void SetFebLength(BOOL bIsLeap);
  43. void ResetFebLength();
  44.  
  45.  
  46.  
  47. ////////////////////////////////// Statics ////////////////////////////////////
  48.  
  49. CString CDate::sm_sBuffer         = _T(""); 
  50. CString CDate::sm_sDefaultFormat  = _T("%d/%m/%c");  
  51. WORD    CDate::sm_wBeginOfWeek    = MONDAY;
  52. LONG    CDate::sm_lEndJulianYear  = 1582;
  53. WORD    CDate::sm_wEndJulianMonth = 10;
  54. WORD    CDate::sm_wEndJulianDay   = 4;
  55. LONG    CDate::sm_lBeginGregYear  = 1582;
  56. WORD    CDate::sm_wBeginGregMonth = 10; 
  57. WORD    CDate::sm_wBeginGregDay   = 15;
  58. BOOL    CDate::sm_bDoAsserts = TRUE;
  59.  
  60. CString CLTimeSpan::sm_sBuffer = _T("");
  61. CString CLTimeSpan::sm_sDefaultFormat = _T("%D %H:%M:%S.%F"); 
  62. BOOL    CLTimeSpan::sm_bDoAsserts = TRUE;
  63.  
  64. CString CLTimeOfDay::sm_sBuffer = _T("");  
  65. CString CLTimeOfDay::sm_sDefaultFormat = _T("%H:%M:%S.%F");
  66. BOOL    CLTimeOfDay::sm_bDoAsserts = TRUE;    
  67.  
  68. CString CLDate::sm_sBuffer = _T("");
  69. CString CLDate::sm_sDefaultFormat = _T("%H:%M:%S.%F %d/%m/%c %t"); 
  70. BOOL    CLDate::sm_bDoAsserts     = TRUE;
  71. BOOL    CLDate::sm_bIsDst         = TRUE;
  72.  
  73.  
  74.  
  75. static const int DeltaTTable[187] =
  76.  {1240, 1150, 1060, 980, 910, 850, 790, 740, 700, 650,
  77.   620, 580, 550, 530, 500, 480, 460, 440, 420, 400, 
  78.   370, 350, 330, 310, 280, 260, 240, 220, 200, 180, 
  79.   160, 140, 130, 120, 110, 100,  90,  90,  90,  90, 
  80.    90,  90,  90,  90, 100, 100, 100, 100, 100, 110, 
  81.   110, 110, 110, 110, 110, 110, 110, 120, 120, 120,
  82.   120, 120, 130, 130, 130, 130, 140, 140, 140, 150,
  83.   150, 150, 150, 160, 160, 160, 160, 160, 170, 170,
  84.   170, 170, 170, 170, 170, 170, 160, 160, 150, 140,
  85.   137, 131, 127, 125, 125, 125, 125, 125, 125, 123,
  86.   120, 114, 106,  96,  86,  75,  66,  60,  57,  56, 
  87.    57,  59,  62,  65,  68,  71,  73,  75,  77,  78,
  88.    79,  75,  64,  54,  29,  16, -10, -27, -36, -47,
  89.   -54, -52, -55, -56, -58, -59, -62, -64, -61, -47,
  90.   -27,   0,  26,  54,  77, 105, 134, 160, 182, 202,
  91.   212, 224, 235, 239, 243, 240, 239, 239, 237, 240,
  92.   243, 253, 262, 273, 282, 291, 300, 307, 314, 322,
  93.   331, 340, 350, 365, 383, 402, 422, 445, 465, 485,
  94.   505, 522, 538, 549, 558, 569, 580};
  95.  
  96. static WORD MonthLength[14] =
  97.   {
  98.   0,  31, 28, 31, 30, 31, 30,
  99.   31, 31, 30, 31, 30, 31, 0};
  100.  
  101.  
  102.  
  103.  
  104. ////////////////////////////////// Implementation /////////////////////////////
  105.             
  106.  
  107.  
  108. //Free Sub-Programs
  109.  
  110. void SetFebLength(BOOL bIsLeap)
  111. {
  112.   MonthLength[2] = (WORD) (28 + bIsLeap);
  113. }
  114.  
  115. void ResetFebLength()
  116. {
  117.   MonthLength[2] = 28;
  118. };
  119.  
  120. LONG lfloor(LONG a, LONG b)
  121. {
  122.   ASSERT(b > 0);
  123.   return (a >= 0L ? a/b : (a%b == 0L) - 1 - labs(a)/b);
  124. }
  125.  
  126.  
  127. //CDate Implementation
  128.  
  129. CDate::CDate(LONG Year, WORD Month, WORD Day)
  130.   Set(Year, Month, Day);
  131. }
  132.  
  133. CDate::CDate(const SYSTEMTIME& st)
  134. {
  135.   Set(st);
  136. }
  137.  
  138. CDate::CDate(LONG Year, WORD Month, WORD WeekOfMonth, WORD DayOfWeek)
  139. {
  140.   Set(Year, Month, WeekOfMonth, DayOfWeek);
  141. }
  142.  
  143. CDate::CDate(LONG Days, DateEpoch e)
  144. {
  145.   Set(Days, e);
  146. }
  147.  
  148. CDate::CDate()
  149. {
  150.   Set();
  151. }
  152.  
  153. CDate::CDate(const CDate& d)
  154. {
  155.   m_lDays = d.m_lDays;
  156.   m_bInGregCalendar = d.m_bInGregCalendar;
  157. }
  158.  
  159. CDate::CDate(const CTime& ctime)
  160. {
  161.   Set(ctime.GetTime()/86400, EPOCH_CTIME);
  162. }
  163.                                      
  164. #ifdef _WIN32
  165. CDate::CDate(const COleDateTime& oleTime)
  166. {
  167.   Set(oleTime);
  168. }                     
  169. #endif
  170.  
  171. CDate& CDate::Set()
  172. {
  173.   m_lDays = LONG_MIN;
  174.   m_bInGregCalendar = FALSE;
  175.   return *this;
  176. }
  177.  
  178. CDate& CDate::Set(LONG Year, WORD Month, WORD Day)
  179. {
  180.   //The following method has been taken from the magazine "Microsoft Systems Journal"
  181.   //I cannot find the copy again, so if anyone recognises the algorithm please let
  182.   //me know so I can credit the author.
  183.  
  184.   if (Month < JANUARY || Month > DECEMBER ||
  185.       Day > DaysInMonth(Month, IsLeap(Year)))
  186.   {
  187.     if (sm_bDoAsserts)
  188.       ASSERT(FALSE);
  189.     Set();
  190.     return *this;
  191.   }
  192.   
  193.   if (((Year > sm_lEndJulianYear) && (Year < sm_lBeginGregYear)) ||
  194.       ((Year == sm_lEndJulianYear) && ((Month > sm_wEndJulianMonth) && (Month < sm_wBeginGregMonth))) ||
  195.       ((Year == sm_lEndJulianYear) && (Month == sm_wEndJulianMonth) && (Day > sm_wEndJulianDay) && (Day < sm_wBeginGregDay)))
  196.   {
  197.     if (sm_bDoAsserts)
  198.       ASSERT(FALSE);
  199.     Set();
  200.     return *this;
  201.   }
  202.  
  203.   SetFebLength(IsLeap(Year));
  204.   m_lDays = (Year-1)*365 + lfloor(Year-1, 4L);
  205.   m_bInGregCalendar = InGregorianCalendar(Year, Month, Day);
  206.   if (m_bInGregCalendar)
  207.     m_lDays += lfloor(Year-1, 400L) - lfloor(Year-1, 100L);
  208.   while (--Month)
  209.     m_lDays += MonthLength[Month];
  210.   m_lDays += Day - 577736L - 2*(!m_bInGregCalendar);
  211.   ResetFebLength();
  212.  
  213.   return *this;
  214. }
  215.  
  216. CDate& CDate::Set(LONG Year, WORD Month, WORD WeekOfMonth, WORD DayOfWeek)
  217. {
  218.   if (WeekOfMonth < 1 || WeekOfMonth > 5 || DayOfWeek < 1 && DayOfWeek > 7)
  219.   {
  220.     if (sm_bDoAsserts)
  221.       ASSERT(FALSE);
  222.     Set();
  223.     return *this;
  224.   }
  225.  
  226.   if (WeekOfMonth < 5)
  227.   {
  228.     CDate FirstMonth(Year, Month, 1);
  229.     if (!FirstMonth.IsValid())
  230.     {
  231.       if (sm_bDoAsserts)
  232.         ASSERT(FALSE);
  233.       Set();
  234.       return *this;
  235.     }
  236.     WORD dow = FirstMonth.GetDayOfWeek();
  237.     WORD Day = (WORD) (((DayOfWeek - dow + 7) % 7) + (7*(WeekOfMonth-1)) + 1);
  238.     Set(Year, Month, Day);
  239.   }
  240.   else  //5 means the last week of the month
  241.   {
  242.     WORD NewMonth = (WORD) (Month + 1);
  243.     LONG NewYear = Year;
  244.     if (NewMonth > DECEMBER)
  245.     {
  246.       Month = 1;
  247.       ++Year;
  248.     }
  249.        
  250.     Set(NewYear, NewMonth, 1, DayOfWeek);
  251.     AddWeek(-1);
  252.   }
  253.  
  254.   return *this;
  255. }
  256.  
  257. CDate& CDate::Set(LONG Days, DateEpoch e)
  258. {
  259.   switch (e)
  260.   {
  261.     case EPOCH_GREG:
  262.     {
  263.       m_lDays = Days;
  264.       break;
  265.     }
  266.     case EPOCH_JD:    
  267.     {
  268.       m_lDays = Days - 2299161;  //-2299161 coresponds to the GDN of JD Epoch namely 1 January -4712 
  269.       break;
  270.     }
  271.     case EPOCH_MJD:   
  272.     {
  273.       m_lDays = Days + 100839L;  //100839 coresponds to the GDN of MJD Epoch namely 17 November 1858 
  274.       break;
  275.     }
  276.     case EPOCH_1900:
  277.     {
  278.       m_lDays = Days + 115860L;  //115860 corresponds to the GDN of 1 January 1900
  279.       break;
  280.     }
  281.     case EPOCH_1950:
  282.     {
  283.       m_lDays = Days + 134122L;  //134122 corresponds to the GDN of 1 January 1950
  284.       break;
  285.     }
  286.     case EPOCH_CTIME:
  287.     {
  288.       m_lDays = Days + 141427L;  //141427 corresponds to the GDN of 1 January 1970
  289.       break;
  290.     }
  291.     case EPOCH_2000:  
  292.     {
  293.       m_lDays = Days + 152384L;  //152384 corresponds to the GDN of 1 January 2000
  294.       break;
  295.     }
  296.     default: ASSERT(FALSE); //should not occur
  297.   }
  298.     
  299.   if (m_lDays > 2146905911)  //Largest valid GDN
  300.   {
  301.     if (sm_bDoAsserts)
  302.       ASSERT(FALSE);
  303.     Set();
  304.   }
  305.  
  306.   m_bInGregCalendar = *this > CDate(sm_lBeginGregYear, sm_wBeginGregMonth, sm_wBeginGregDay);
  307.  
  308.   return *this;
  309. }
  310.  
  311. CDate& CDate::Set(const SYSTEMTIME& st)
  312. {
  313.   Set(st.wYear, st.wMonth, st.wDay);
  314.   return *this;
  315. }
  316.  
  317. CDate& CDate::Set(const CTime& ctime)
  318. {
  319.   return Set(ctime.GetTime()/86400, EPOCH_CTIME);
  320. }
  321.       
  322. #ifdef _WIN32
  323. CDate& CDate::Set(const COleDateTime& oleTime)
  324. {
  325.   return Set((LONG) oleTime.GetYear(), (WORD) oleTime.GetMonth(), (WORD) oleTime.GetDay());
  326. }                     
  327. #endif
  328.  
  329. CDate CDate::CurrentDate()
  330. {   
  331.   #ifdef _WIN32
  332.     SYSTEMTIME st;
  333.     ::GetLocalTime(&st);
  334.     return CDate(st);
  335.   #else      
  336.     time_t csecs = time(NULL);
  337.     tm* ct = localtime(&csecs);
  338.     return CDate((LONG) (ct->tm_year + 1900), (WORD) (ct->tm_mon + 1), (WORD) (ct->tm_mday));
  339.   #endif
  340. }
  341.  
  342. WORD CDate::CurrentMonth()
  343. {              
  344.   return CurrentDate().GetMonth();
  345. }
  346.  
  347. WORD CDate::CurrentDay()
  348. {
  349.   return CurrentDate().GetDay();
  350. }
  351.  
  352. LONG CDate::CurrentYear()
  353. {                               
  354.   return CurrentDate().GetYear();
  355. }
  356.  
  357. WORD CDate::CurrentDayOfWeek()
  358. {            
  359.   return CurrentDate().GetDayOfWeek();
  360. }
  361.  
  362. void CDate::SetBeginingDayOfWeek(WORD BeginOfWeek)
  363. {
  364.   sm_wBeginOfWeek = BeginOfWeek;
  365. }
  366.  
  367. WORD CDate::GetBeginingDayOfWeek()
  368. {
  369.   return sm_wBeginOfWeek;
  370. }
  371.  
  372. void CDate::SetEndJulianCalendar(LONG Year, WORD Month, WORD Day)
  373. {
  374.   sm_lEndJulianYear = Year;
  375.   sm_wEndJulianMonth = Month;
  376.   sm_wEndJulianDay = Day;
  377. }
  378.  
  379. void CDate::SetBeginGregCalendar(LONG Year, WORD Month, WORD Day)
  380. {
  381.   sm_lBeginGregYear = Year;
  382.   sm_wBeginGregMonth = Month;
  383.   sm_wBeginGregDay = Day;
  384. }
  385.  
  386. DateS CDate::GetEndJulianCalendar()
  387. {
  388.   DateS rVal;
  389.   rVal.lYear = sm_lEndJulianYear;
  390.   rVal.wMonth = sm_wEndJulianMonth;
  391.   rVal.wDay = sm_wEndJulianDay;
  392.   rVal.wWday = CDate(sm_lEndJulianYear, sm_wEndJulianMonth, sm_wEndJulianDay).GetDayOfWeek();
  393.   rVal.wYday = DaysSinceJan0(sm_wEndJulianMonth, sm_wEndJulianDay, IsLeap(sm_lEndJulianYear));
  394.   rVal.ct = JULIAN;
  395.   return rVal;
  396. }
  397.  
  398. DateS CDate::GetBeginGregCalendar()
  399. {
  400.   DateS rVal;
  401.   rVal.lYear = sm_lBeginGregYear;
  402.   rVal.wMonth = sm_wBeginGregMonth;
  403.   rVal.wDay = sm_wBeginGregDay;
  404.   rVal.wWday = CDate(sm_lBeginGregYear, sm_wBeginGregMonth, sm_wBeginGregDay).GetDayOfWeek();
  405.   rVal.wYday = DaysSinceJan0(sm_wBeginGregMonth, sm_wBeginGregDay, IsLeap(sm_lBeginGregYear));
  406.   rVal.ct = GREGORIAN;
  407.   return rVal;
  408. }
  409.  
  410. BOOL CDate::InGregorianCalendar(LONG Year, WORD Month, WORD Day)
  411. {
  412.   if (Year == sm_lBeginGregYear)
  413.   {
  414.     if (Month == sm_wBeginGregMonth)
  415.       return (Day >= sm_wBeginGregDay);
  416.     else
  417.       return (Month > sm_wBeginGregMonth);
  418.   }
  419.   else
  420.     return (Year > sm_lBeginGregYear);
  421. }
  422.  
  423. #ifdef _DEBUG
  424. BOOL CDate::SetDoConstructorAsserts(BOOL bDoAsserts)
  425. {
  426.   BOOL bOldDoAsserts = sm_bDoAsserts;
  427.   sm_bDoAsserts = bDoAsserts;
  428.   return bOldDoAsserts;
  429. }
  430. #endif
  431.  
  432. CString& CDate::GetFullStringDayOfWeek(WORD DayOfWeek)
  433. {
  434.   sm_sBuffer.Empty();
  435.   if (DayOfWeek > 0 && DayOfWeek <= 7)
  436.   {
  437.     if (!sm_sBuffer.LoadString(IDS_WEEKDAY1 - 1 + DayOfWeek))
  438.       ASSERT(FALSE);
  439.   }
  440.   return sm_sBuffer;
  441. }
  442.  
  443. CString& CDate::GetAbrStringDayOfWeek(WORD DayOfWeek)
  444. {
  445.   sm_sBuffer.Empty();
  446.   if (DayOfWeek > 0 && DayOfWeek <= 7)
  447.   {
  448.     if (!sm_sBuffer.LoadString(IDS_ABR_WEEKDAY1 - 1 + DayOfWeek))
  449.       ASSERT(FALSE);
  450.   }
  451.   return sm_sBuffer;
  452. }
  453.  
  454. CString& CDate::GetFullStringMonth(WORD Month)
  455. {
  456.   sm_sBuffer.Empty();
  457.   if (Month > 0 && Month <= 12)
  458.   {
  459.     if (!sm_sBuffer.LoadString(IDS_MONTH1 - 1 + Month))
  460.       ASSERT(FALSE);
  461.   }
  462.   return sm_sBuffer;
  463. }
  464.  
  465. CString& CDate::GetAbrStringMonth(WORD Month)
  466. {
  467.   sm_sBuffer.Empty();
  468.   if (Month > 0 && Month <= 12)
  469.   {
  470.     if (!sm_sBuffer.LoadString(IDS_ABR_MONTH1 - 1 + Month))
  471.       ASSERT(FALSE);
  472.   }
  473.   return sm_sBuffer;
  474. }
  475.  
  476. CDate CDate::FirstCurrentMonth()
  477. {
  478.   CDate c = CDate::CurrentDate();
  479.   return CDate(c.GetYear(), c.GetMonth(), 1); 
  480. }
  481.  
  482. CDate CDate::LastCurrentMonth()
  483. {
  484.   CDate c = CDate::CurrentDate();
  485.   return CDate(c.GetYear(), c.GetMonth(), c.DaysInMonth()); 
  486. }
  487.  
  488. CDate CDate::FirstCurrentYear()
  489. {
  490.   CDate c = CDate::CurrentDate();
  491.   return CDate(c.GetYear(), 1, 1); 
  492. }              
  493.  
  494. CDate CDate::LastCurrentYear()
  495. {
  496.   CDate c = CDate::CurrentDate();
  497.   return CDate(c.GetYear(), 12, CDate::DaysInMonth(12, c.IsLeap())); 
  498. }
  499.  
  500. CDate CDate::JDEpoch()
  501. {
  502.   return CDate(0, EPOCH_JD);
  503. }
  504.  
  505. CDate CDate::MJDEpoch()
  506. {
  507.   return CDate(0, EPOCH_MJD);
  508. }
  509.  
  510. CDate CDate::Epoch1900()
  511. {
  512.   return CDate(0, EPOCH_1900);
  513. }
  514.  
  515. CDate CDate::Epoch1950()
  516. {
  517.   return CDate(0, EPOCH_1950);
  518. }
  519.  
  520. CDate CDate::EpochCTime()
  521. {
  522.   return CDate(0, EPOCH_CTIME);
  523. }
  524.  
  525. CDate CDate::Epoch2000()
  526. {
  527.   return CDate(0, EPOCH_2000);
  528. }
  529.  
  530. CDate CDate::GregorianEpoch()
  531. {
  532.   return CDate(0, EPOCH_GREG);
  533. }                 
  534.  
  535. void CDate::ClearStatics()
  536. {
  537.   sm_sBuffer.Empty();
  538.   sm_sDefaultFormat.Empty();
  539. }
  540.  
  541. CDate CDate::NewYearsDay(LONG Year) 
  542. {
  543.   return CDate(Year, JANUARY, 1);
  544. }
  545.  
  546. CDate CDate::ValentinesDay(LONG Year) 
  547. {
  548.   return CDate(Year, FEBRUARY, 14);
  549. }
  550.  
  551. CDate CDate::AshWednesday(LONG Year)
  552. {                                      
  553.   return CDate::EasterSunday(Year) - 39L;    //Ash Wednesday occurs 39 days before Easter Sunday
  554. }
  555.  
  556. CDate CDate::StPatricksDay(LONG Year) 
  557. {
  558.   return CDate(Year, MARCH, 17);
  559. }
  560.  
  561. CDate CDate::GoodFriday(LONG Year)
  562.   return CDate::EasterSunday(Year) - 2L;     //Good Friday occurs 2 days before Easter Sunday
  563. }
  564.  
  565. CDate CDate::EasterSunday(LONG Year)
  566. {
  567.   //The following method has been taken from the book "Astronimical Algorithms" by Jean Meeus
  568.   //which was taken in turn from a book "General Astronomy" by Spencer Jones. It has been 
  569.   //published again in the "Journal of the British Astronomical Association, Vol 88" where
  570.   //it is said that it was devised in 1876 and appeared in Butcher's "Ecclesiastical Calendar"
  571.  
  572.   if (InGregorianCalendar(Year, 4, 1))  //in the Gregorain Calendar, Will possibly give results if Calendar
  573.   {                                     //switches from Julian to Gregorian in March or April because then
  574.     int a = (int) (Year % 19);          //the year may be considered Gregorian or Julian
  575.     int b = (int) (Year / 100);
  576.     int c = (int) (Year % 100);
  577.     int d = b / 4;
  578.     int e = b % 4;
  579.     int f = (b+8) / 25;
  580.     int g = (b - f + 1) / 3;
  581.     int h = (19*a + b - d - g + 15) % 30;
  582.     int i = c / 4;
  583.     int k = c % 4;
  584.     int l = (32 + 2*e + 2*i - h -k) % 7;
  585.     int m = (a + 11*h +22*l) / 451;
  586.     int n = (h + l - 7*m + 114) / 31;
  587.     int p = (h + l - 7*m + 114) % 31;
  588.     return CDate(Year, WORD(n), WORD(p+1));
  589.   }
  590.   else              //in the Julian Calendar
  591.   {                          
  592.     int a = (int) (Year % 4);
  593.     int b = (int) (Year % 7);
  594.     int c = (int) (Year % 19);
  595.     int d = (19*c + 15) % 30;
  596.     int e = (2*a + 4*b - d + 34) % 7;
  597.     int f = (d + e + 114) / 31;
  598.     int g = (d + e + 114) % 31;
  599.     return CDate(Year, (WORD) f, (WORD) (g + 1));
  600.   }  
  601. }
  602.  
  603. CDate CDate::CanadaDay(LONG Year)
  604. {
  605.   return CDate(Year, JULY, 1);
  606. }
  607.  
  608. CDate CDate::IndependenceDay(LONG Year) 
  609. {
  610.   return CDate(Year, JULY, 4);
  611. }
  612.  
  613. CDate CDate::BastilleDay(LONG Year) 
  614. {
  615.   return CDate(Year, JULY, 14);
  616. }
  617.  
  618. CDate CDate::ChristmasDay(LONG Year)  
  619. {
  620.   return CDate(Year, DECEMBER, 25);
  621. }
  622.  
  623. BOOL CDate::IsLeap(LONG Year)
  624. {                
  625.   if (InGregorianCalendar(Year, 1, 1))    //Will give incorrect results if Calendar switches
  626.   {                                       //from Julian to Gregorian in the Year 1600 (if any Country did)
  627.     if ((Year % 100) == 0)                
  628.       return ((Year % 400) == 0) ? TRUE : FALSE;
  629.     else
  630.       return ((Year % 4) == 0) ? TRUE : FALSE;
  631.   }
  632.   else                                        
  633.     return ((Year % 4) == 0) ? TRUE : FALSE;
  634.       
  635. }
  636.  
  637. WORD CDate::DaysInYear(LONG Year)
  638. {
  639.   return IsLeap(Year) ? ((WORD) 366) : ((WORD) 365);
  640. }
  641.  
  642. WORD CDate::DaysInMonth(WORD Month, BOOL IsLeap)
  643. {
  644.   SetFebLength(IsLeap);
  645.   ASSERT(Month >= 1 && Month <= 12);
  646.   WORD r = MonthLength[Month];
  647.   ResetFebLength();
  648.   return r;
  649. }
  650.  
  651. WORD CDate::DaysSinceJan1(WORD Month, WORD Day, BOOL IsLeap)
  652. {
  653.   return (WORD) (DaysSinceJan0(Month, Day, IsLeap) - 1);
  654. }
  655.  
  656.  
  657. WORD CDate::DaysSinceJan0(WORD Month, WORD Day, BOOL IsLeap)
  658. {            
  659.   ASSERT(Month >= JANUARY && Month <= DECEMBER);
  660.   ASSERT(Day <= DaysInMonth(Month, IsLeap) && Day >= 1);
  661.   int k = IsLeap ? 1 : 2;
  662.   WORD rVal = (WORD) ((int(275*Month/9)) - (k*int((Month+9)/12)) + Day - 30);
  663.   return rVal; 
  664. }
  665.  
  666. void CDate::SetDefaultFormat(const CString& Format)
  667. {
  668.   sm_sDefaultFormat = Format;
  669. }
  670.  
  671. CString& CDate::GetDefaultFormat()
  672. {
  673.   return sm_sDefaultFormat;
  674. }
  675.  
  676. WORD CDate::DaysSinceJan1() const
  677. {
  678.   AssertValid();
  679.   return (WORD) (*this - CDate(GetYear(), 1, 1));
  680. }
  681.  
  682. WORD CDate::DaysSinceJan0() const
  683. {
  684.   AssertValid();
  685.   return (WORD) (DaysSinceJan1() + 1);
  686. }
  687.  
  688. DateS CDate::GetDate() const
  689. {
  690.   //See the comment in CDate::Set(LONG Year, WORD Month, WORD Day)
  691.   //for references to where the algorithm is taken from
  692.  
  693.   AssertValid();
  694.   BOOL bIsGreg = InGregorianCalendar();
  695.   BOOL bIsJulian = !bIsGreg;
  696.   DateS ds;
  697.   LONG gdn = m_lDays + 577735L + 2*bIsJulian;
  698.   LONG y4 = 1461L;
  699.   LONG y400 = 146100L - 3*bIsGreg;
  700.   LONG y100 = 36525L - bIsGreg;
  701.   BOOL exception=FALSE;
  702.   ds.lYear = 400*lfloor(gdn, y400);
  703.   gdn -= y400*lfloor(gdn, y400);       //400 year periods
  704.   if (gdn > 0L)
  705.   {
  706.     ds.lYear += 100*lfloor(gdn, y100);  //100 year periods
  707.     gdn -= y100*lfloor(gdn, y100);
  708.     exception = (gdn == 0L && bIsGreg);
  709.     if (gdn > 0L)
  710.     {
  711.       ds.lYear += 4*lfloor(gdn, y4);     //4 year periods
  712.       gdn -= y4*lfloor(gdn, y4);
  713.       if (gdn > 0L)
  714.       {
  715.         int i=0;
  716.         while (gdn > 365 && ++i < 4)
  717.         {
  718.           ds.lYear++;
  719.           gdn -= 365L;
  720.         }
  721.       }
  722.     }
  723.   }
  724.   if (exception)
  725.     gdn = 366L; //occurs once every hundred years with Gregorian calendar
  726.   else
  727.   {
  728.     ds.lYear++;
  729.     gdn++;
  730.   }
  731.   SetFebLength(IsLeap(ds.lYear));
  732.   ds.wMonth = 1;
  733.   while (ds.wMonth < 13 && gdn > ((LONG) MonthLength[ds.wMonth]))
  734.     gdn -= MonthLength[ds.wMonth++];
  735.   if (ds.wMonth == 13)
  736.   {
  737.     ds.wMonth = 1;
  738.     ds.lYear++;
  739.   }
  740.   ResetFebLength();
  741.   ds.wDay = (WORD) gdn;
  742.   ds.wWday = (WORD) ((m_lDays+12)%7 + 1); 
  743.   ds.wYday = DaysSinceJan0(ds.wMonth, ds.wDay, IsLeap(ds.lYear));
  744.  
  745.   return ds;
  746. }
  747.  
  748. WORD CDate::GetDay() const
  749. {
  750.   AssertValid();
  751.   return GetDate().wDay;
  752. }
  753.  
  754. WORD CDate::GetMonth() const
  755. {
  756.   AssertValid();
  757.   return GetDate().wMonth;
  758. }
  759.  
  760. LONG CDate::GetYear() const
  761. {
  762.   AssertValid();
  763.   return GetDate().lYear;
  764. }
  765.  
  766. LONG CDate::GetCEBCEYear(BOOL& IsCE) const
  767. {
  768.   AssertValid();
  769.   LONG Year = GetDate().lYear;
  770.  
  771.   if (Year > 0)
  772.   {
  773.     IsCE = TRUE;
  774.     return Year;
  775.   }
  776.   else
  777.   {
  778.     IsCE = FALSE;
  779.     return labs(GetYear() - 1);
  780.   }
  781. }
  782.  
  783. WORD CDate::Get2DigitYear() const
  784. {
  785.   AssertValid();
  786.   LONG Year = labs(GetYear());
  787.   return (WORD) (Year - ((Year/100)*100));
  788. }
  789.  
  790.  
  791. WORD CDate::GetWeekOfYear() const
  792. {               
  793.   AssertValid(); 
  794.   CDate FirstOfYear(GetYear(), JANUARY, 1, GetBeginingDayOfWeek());
  795.   LONG diff = *this - FirstOfYear;
  796.   if (diff < 0)
  797.     return 0;
  798.   else
  799.     return (WORD) (diff/7 + 1);
  800. }
  801.  
  802.  
  803. WORD CDate::GetWeekOfMonth() const
  804. {                  
  805.   AssertValid();
  806.   CDate FirstOfMonth(GetYear(), GetMonth(), 1, GetBeginingDayOfWeek());
  807.   LONG diff = *this - FirstOfMonth;
  808.   if (diff < 0)
  809.     return 0;
  810.   else
  811.     return (WORD) (diff/7 + 1);
  812. }
  813.  
  814. LONG CDate::Since1900Epoch() const
  815. {
  816.   AssertValid();
  817.   return *this - CDate(1900, 1, 1);
  818. }
  819.  
  820. LONG CDate::Since1950Epoch() const
  821. {
  822.   AssertValid();
  823.   return *this - CDate(1950, 1, 1);
  824. }
  825.  
  826. LONG CDate::SinceCTimeEpoch() const
  827. {
  828.   AssertValid();  
  829.   return *this - CDate(1970, 1, 1);
  830. }
  831.  
  832. LONG CDate::Since2000Epoch() const
  833. {
  834.   AssertValid();
  835.   return *this - CDate(2000, 1, 1);
  836. }
  837.  
  838. LONG CDate::JD() const
  839. {
  840.   AssertValid();
  841.   return *this - JDEpoch();
  842. }
  843.  
  844. LONG CDate::GDN() const
  845. {
  846.   AssertValid();
  847.   return m_lDays;
  848. }
  849.  
  850. BOOL CDate::IsLeap() const
  851. {
  852.   AssertValid();
  853.   return IsLeap(GetYear());
  854. }
  855.  
  856. WORD CDate::DaysInYear() const
  857.   AssertValid();
  858.   return DaysInYear(GetYear());
  859. }
  860.  
  861. WORD CDate::DaysInMonth() const
  862. {
  863.   AssertValid();
  864.   return DaysInMonth(GetMonth(), IsLeap());
  865. }
  866.  
  867. void CDate::AddYear(int Years)
  868. {
  869.   AssertValid();
  870.   LONG Months = Years*12;
  871.   if (Months >= INT_MIN && Months <= INT_MAX)
  872.     AddMonth((int) Months);
  873.   else
  874.   {
  875.     ASSERT(FALSE);
  876.     Set();
  877.   }
  878. }
  879.  
  880. void CDate::AddMonth(int Months)
  881. {
  882.   AssertValid();
  883.   LONG NewMonth = (LONG) GetMonth();
  884.   LONG NewYear = GetYear();
  885.   NewMonth += Months;
  886.   if ((NewMonth > DECEMBER) || (NewMonth < JANUARY))
  887.   {
  888.     NewYear += NewMonth / 12;
  889.     NewMonth = NewMonth % 12;
  890.   }
  891.   if (NewMonth < JANUARY)
  892.   {
  893.     --NewYear;
  894.     NewMonth += 12;
  895.   }
  896.  
  897.   WORD Day = GetDay();
  898.  
  899.   WORD MaxDays = DaysInMonth((WORD) NewMonth, IsLeap(NewYear));
  900.   if (Day > MaxDays)
  901.     Day = MaxDays;
  902.   Set(NewYear, (WORD) NewMonth, Day);
  903. }
  904.  
  905. void CDate::AddWeek(int Weeks)
  906. {
  907.   AssertValid();
  908.   *this += 7L*((LONG)Weeks);
  909. }
  910.  
  911. WORD CDate::GetDayOfWeek() const
  912. {
  913.   AssertValid();
  914.   return GetDate().wWday;
  915. }
  916.  
  917. CString& CDate::GetStringCEBCEYear() const
  918. {
  919.   AssertValid();
  920.   BOOL bIsCEYear;
  921.   LONG lCEYear = GetCEBCEYear(bIsCEYear);
  922.   CString sYear;                    
  923.   sYear.Format(_T("%ld"), lCEYear);
  924.   if (bIsCEYear)
  925.     AfxFormatString1(sm_sBuffer, IDS_CEYEAR, sYear);
  926.   else
  927.     AfxFormatString1(sm_sBuffer, IDS_BCEYEAR, sYear);
  928.   return sm_sBuffer;
  929. }
  930.  
  931. CString& CDate::GetFullStringDayOfWeek() const
  932. {
  933.   AssertValid();
  934.   return GetFullStringDayOfWeek(GetDayOfWeek());
  935. }
  936.  
  937. CString& CDate::GetAbrStringDayOfWeek() const
  938. {
  939.   AssertValid();
  940.   return GetAbrStringDayOfWeek(GetDayOfWeek());
  941. }
  942.  
  943. CString& CDate::GetFullStringMonth() const
  944. {
  945.   AssertValid();
  946.   return GetFullStringMonth(GetMonth());
  947. }
  948.  
  949. CString& CDate::GetAbrStringMonth() const
  950. {
  951.   AssertValid();
  952.   return GetAbrStringMonth(GetMonth());
  953. }
  954.  
  955. SYSTEMTIME CDate::GetSYSTEMTIME() const
  956. {
  957.   AssertValid();
  958.   SYSTEMTIME s;
  959.   s.wYear = 0;
  960.   s.wMonth = 0;
  961.   s.wDayOfWeek = 0;
  962.   s.wDay = 0;
  963.   s.wHour = 0;
  964.   s.wMinute = 0;
  965.   s.wSecond = 0;
  966.   s.wMilliseconds = 0;
  967.  
  968.   DateS ds = GetDate();
  969.  
  970.   //handle range errors
  971.   if ((ds.lYear < 0) || (ds.lYear > USHRT_MAX))
  972.   {
  973.     ASSERT(FALSE);
  974.     s.wYear = 0;
  975.     return s;
  976.   }
  977.   
  978.   s.wYear = (WORD) ds.lYear;
  979.   s.wMonth = ds.wMonth;
  980.   s.wDayOfWeek = (WORD) (ds.wWday - 1);  //SYSTEMTIME uses 0 based indices
  981.   s.wDay = ds.wDay;
  982.  
  983.   return s;
  984. }                
  985.                           
  986. tm CDate::GetTM() const
  987. {
  988.   AssertValid();
  989.   tm rVal;
  990.   
  991.   rVal.tm_sec   = 0;
  992.   rVal.tm_min   = 0;
  993.   rVal.tm_hour  = 0;
  994.   rVal.tm_mday  = 0;
  995.   rVal.tm_mon   = 0;
  996.   rVal.tm_year  = 0;
  997.   rVal.tm_wday  = 0;
  998.   rVal.tm_yday  = 0;
  999.   rVal.tm_isdst = 0;
  1000.  
  1001.   DateS ds = GetDate(); 
  1002.      
  1003. #ifdef _WIN32
  1004.   long MinYear = 1900L + LONG_MIN;
  1005.   long MaxYear = LONG_MAX;
  1006. #else   
  1007.   long MinYear = 1900L + SHRT_MIN;
  1008.   long MaxYear = 1900L + SHRT_MAX;
  1009. #endif
  1010.  
  1011.   //handle range errors
  1012.   if ((ds.lYear < MinYear) || (ds.lYear > MaxYear))
  1013.   {
  1014.     ASSERT(FALSE);
  1015.     return rVal;
  1016.   }
  1017.   
  1018.   rVal.tm_year = (int) (ds.lYear - 1900L);
  1019.   rVal.tm_mon = ds.wMonth - 1;  //tm struct uses 0 based indices
  1020.   rVal.tm_wday = ds.wWday - 1;  //tm struct uses 0 based indices
  1021.   rVal.tm_mday = ds.wDay; 
  1022.   rVal.tm_wday = ds.wYday - 1; //Returns days since Jan 1
  1023.               
  1024.   return rVal;
  1025. }
  1026.  
  1027. BOOL CDate::IsValid() const
  1028. {
  1029.   return (m_lDays == LONG_MIN) ? FALSE : TRUE;
  1030. }
  1031.  
  1032. LONG CDate::Collate() const
  1033. {
  1034.   AssertValid();
  1035.   DateS s;
  1036.   s = GetDate();
  1037.   return (s.lYear*10000) + (s.wMonth*100) + s.wDay;
  1038. }
  1039.  
  1040. BOOL CDate::InGregorianCalendar() const
  1041. {
  1042.   AssertValid();
  1043.   return m_bInGregCalendar;
  1044. }
  1045.  
  1046. CDate CDate::FirstThisMonth() const
  1047. {
  1048.   AssertValid();
  1049.   DateS s=GetDate();
  1050.   return CDate(s.lYear, s.wMonth, 1);  
  1051. }
  1052.  
  1053. CDate CDate::LastThisMonth() const
  1054. {
  1055.   AssertValid();
  1056.   DateS s = GetDate();
  1057.   return CDate(s.lYear, s.wMonth, DaysInMonth(s.wMonth, IsLeap(s.lYear)));  
  1058. }
  1059.  
  1060. CDate CDate::FirstThisYear() const
  1061. {
  1062.   AssertValid();
  1063.   DateS s = GetDate();
  1064.   CDate d(s.lYear, JANUARY, 1);
  1065.   return d;  
  1066. }
  1067.  
  1068. CDate CDate::LastThisYear() const
  1069. {
  1070.   AssertValid();
  1071.   DateS s = GetDate();
  1072.   CDate d(s.lYear, DECEMBER, 1);
  1073.   return d;  
  1074. }
  1075.  
  1076. CDate& CDate::operator=(const CDate& d)
  1077. {
  1078.   m_lDays = d.m_lDays;
  1079.   m_bInGregCalendar = d.m_bInGregCalendar;
  1080.   return *this;
  1081. }
  1082.  
  1083. CDate CDate::operator+(LONG Days) const
  1084. {
  1085.   AssertValid();
  1086.   return CDate(m_lDays + Days, EPOCH_GREG);
  1087. }
  1088.  
  1089. LONG CDate::operator-(const CDate& d) const
  1090. {
  1091.   AssertValid();
  1092.   return m_lDays - d.m_lDays;
  1093. }
  1094.  
  1095. CDate CDate::operator-(LONG Days) const
  1096. {
  1097.   AssertValid();
  1098.   return CDate(m_lDays - Days, EPOCH_GREG);
  1099. }
  1100.  
  1101. CDate& CDate::operator+=(LONG Days)
  1102. {
  1103.   AssertValid();
  1104.   m_lDays += Days;
  1105.   return *this;
  1106. }
  1107.  
  1108. CDate& CDate::operator-=(LONG Days)
  1109. {
  1110.   AssertValid();
  1111.   m_lDays -= Days;
  1112.   return *this;
  1113. }
  1114.  
  1115. CDate& CDate::operator++()
  1116. {
  1117.   AssertValid();
  1118.   m_lDays++;
  1119.   return *this;
  1120. }
  1121.  
  1122. CDate& CDate::operator--()
  1123. {
  1124.   AssertValid();
  1125.   m_lDays--;
  1126.   return *this;
  1127. }
  1128.  
  1129. BOOL CDate::operator==(const CDate& d) const
  1130. {
  1131.   AssertValid();
  1132.   return m_lDays == d.m_lDays;
  1133. }
  1134.  
  1135. BOOL CDate::operator>(const CDate& d) const
  1136. {
  1137.   AssertValid();
  1138.   return m_lDays > d.m_lDays;
  1139. }
  1140.  
  1141. BOOL CDate::operator>=(const CDate& d) const
  1142. {
  1143.   AssertValid();
  1144.   return m_lDays >= d.m_lDays;
  1145. }
  1146.  
  1147. BOOL CDate::operator<(const CDate& d) const
  1148. {
  1149.   AssertValid();
  1150.   return m_lDays < d.m_lDays;
  1151. }
  1152.  
  1153. BOOL CDate::operator<=(const CDate& d) const
  1154. {
  1155.   AssertValid();
  1156.   return m_lDays <= d.m_lDays;
  1157. }
  1158.  
  1159. BOOL CDate::operator!=(const CDate& d) const
  1160. {
  1161.   AssertValid();
  1162.   return m_lDays != d.m_lDays;
  1163. }
  1164.  
  1165. #ifdef _DEBUG
  1166. void CDate::AssertValid() const
  1167. {
  1168.   CObject::AssertValid();
  1169.   ASSERT(IsValid());
  1170. }
  1171. #endif
  1172.  
  1173. #ifdef _DEBUG
  1174. void CDate::Dump(CDumpContext& dc) const
  1175. {
  1176.   CObject::Dump(dc);
  1177.   dc << Format() << _T("\n");
  1178. }
  1179. #endif
  1180.  
  1181. /*    //The Following Format parameters are supported
  1182.  
  1183. %a    Abbreviated weekday name
  1184. %A    Full weekday name
  1185. %b    Abbreviated month name
  1186. %B    Full month name
  1187. %d    Day of month as decimal number (01 - 31)
  1188. %j    Day of year as decimal number (001 - 366)
  1189. %m    Month as decimal number (01 - 12)
  1190. %U    Week of year as decimal number
  1191. %w    Weekday as decimal number (1 - 7; Sunday is 1)
  1192. %x    Short date representation, appropriate to current locale
  1193. %y    Year without century, as decimal number (00 - 99)
  1194. %Y    Year with century, as decimal number
  1195. %c    Year displayed using C.E.(Current Epoch) / B.C.E (Before Current Epoch) convention e.g. -1023 = 1022 BCE
  1196. %#x   Long date representation, appropriate to current locale
  1197. %#d, %#j, %#m, %#U, %#y Remove leading zeros (if any)
  1198. */
  1199. CString& CDate::Format(const CString& sFormat) const
  1200.   if (!IsValid())
  1201.     sm_sBuffer.Empty();
  1202.   else
  1203.   {
  1204.     CString sBuffer;
  1205.     sm_sBuffer.Empty();
  1206.     CString rVal;
  1207.     int sFmtLength = sFormat.GetLength();
  1208.  
  1209.     for (int i=0; i<sFmtLength; i++)
  1210.     {
  1211.       TCHAR c = sFormat.GetAt(i);
  1212.       if (c == TCHAR('%'))
  1213.       {
  1214.         ++i;
  1215.         if (i < sFmtLength)
  1216.         {
  1217.           c = sFormat.GetAt(i);
  1218.           switch (c)
  1219.           {
  1220.             case TCHAR('a'):
  1221.             {
  1222.               rVal += GetAbrStringDayOfWeek();
  1223.               break;
  1224.             }
  1225.             case TCHAR('A'):
  1226.             {
  1227.               rVal += GetFullStringDayOfWeek();
  1228.               break;
  1229.             }
  1230.             case TCHAR('b'):
  1231.             {
  1232.               rVal += GetAbrStringMonth();
  1233.               break;
  1234.             }
  1235.             case TCHAR('c'):
  1236.             {
  1237.               rVal += GetStringCEBCEYear();
  1238.               break;
  1239.             }
  1240.             case TCHAR('B'):
  1241.             {
  1242.               rVal += GetFullStringMonth();
  1243.               break;
  1244.             }
  1245.             case TCHAR('d'):
  1246.             {
  1247.               sBuffer.Format(_T("%.02d"), GetDay());
  1248.               rVal += sBuffer;
  1249.               break;
  1250.             }
  1251.             case TCHAR('j'):
  1252.             {
  1253.               sBuffer.Format(_T("%.03d"), DaysSinceJan0());
  1254.               rVal += sBuffer;
  1255.               break;
  1256.             }
  1257.             case TCHAR('m'):
  1258.             {
  1259.               sBuffer.Format(_T("%.02d"), GetMonth());
  1260.               rVal += sBuffer;
  1261.               break;
  1262.             }
  1263.             case TCHAR('U'):
  1264.             {
  1265.               sBuffer.Format(_T("%.02d"), GetWeekOfYear());
  1266.               rVal += sBuffer;
  1267.               break;
  1268.             }
  1269.             case TCHAR('w'):
  1270.             {
  1271.               sBuffer.Format(_T("%d"), GetDayOfWeek());
  1272.               rVal += sBuffer;
  1273.               break;
  1274.             }                                   
  1275.             
  1276.           #ifdef _WIN32
  1277.             case TCHAR('x'):
  1278.             {
  1279.               sBuffer.Empty();
  1280.               SYSTEMTIME st = GetSYSTEMTIME();
  1281.               int Res = ::GetDateFormat(LOCALE_USER_DEFAULT,
  1282.                                       DATE_SHORTDATE,
  1283.                                       &st,
  1284.                                       NULL,
  1285.                                       sBuffer.GetBufferSetLength(100),
  1286.                                       100); 
  1287.               if (Res == 0)
  1288.                 TRACE1("GetDateFormat() Failed in CDate::Format(), GetLastError() returned %ul\n", ::GetLastError());
  1289.               sBuffer.ReleaseBuffer();
  1290.               rVal += sBuffer;
  1291.               break;
  1292.             }                 
  1293.           #else
  1294.             #ifndef _WINDLL  //only available when statically linked to CRT
  1295.               case TCHAR('x'):
  1296.               {
  1297.                 sBuffer.Empty();                                            
  1298.                 tm tmCDate = GetTM();
  1299.                 strftime(sBuffer.GetBufferSetLength(200), 200, "%x", &tmCDate);
  1300.                 sBuffer.ReleaseBuffer();
  1301.                 rVal += sBuffer;
  1302.                 break;
  1303.               }    
  1304.             #endif               
  1305.           #endif
  1306.             
  1307.             case TCHAR('y'):
  1308.             {
  1309.               LONG Year = GetYear();
  1310.               sBuffer.Format(_T("%.02d"), Get2DigitYear());
  1311.               rVal += sBuffer;
  1312.               break;
  1313.             }
  1314.             case TCHAR('Y'):
  1315.             {
  1316.               sBuffer.Format(_T("%ld"), GetYear());
  1317.               rVal += sBuffer;
  1318.               break;
  1319.             }
  1320.             case TCHAR('#'):
  1321.             {
  1322.               if (i < sFmtLength)
  1323.               {
  1324.                 ++i;
  1325.                 c = sFormat.GetAt(i);
  1326.                 switch (c)
  1327.                 {
  1328.                   case TCHAR('d'):
  1329.                   {
  1330.                     sBuffer.Format(_T("%d"), GetDay());
  1331.                     rVal += sBuffer;
  1332.                     break;
  1333.                   }
  1334.                   case TCHAR('j'):
  1335.                   {
  1336.                     sBuffer.Format(_T("%d"), DaysSinceJan0());
  1337.                     rVal += sBuffer;
  1338.                     break;
  1339.                   }
  1340.                   case TCHAR('m'):
  1341.                   {
  1342.                     sBuffer.Format(_T("%d"), GetMonth());
  1343.                     rVal += sBuffer;
  1344.                     break;
  1345.                   }
  1346.                   case TCHAR('U'):
  1347.                   {
  1348.                     sBuffer.Format(_T("%d"), GetWeekOfYear());
  1349.                     rVal += sBuffer;
  1350.                     break;
  1351.                   }                                    
  1352.                   
  1353.                 #ifdef _WIN32
  1354.                   case TCHAR('x'):
  1355.                   {
  1356.                     sBuffer.Empty();
  1357.                     SYSTEMTIME st = GetSYSTEMTIME();
  1358.                     int Res = ::GetDateFormat(LOCALE_USER_DEFAULT,
  1359.                                             DATE_LONGDATE,
  1360.                                             &st,
  1361.                                             NULL,
  1362.                                             sBuffer.GetBufferSetLength(100),
  1363.                                             100); 
  1364.                     if (Res == 0)
  1365.                       TRACE1("GetDateFormat() Failed in CDate::Format(), GetLastError() returned %ul\n", ::GetLastError());
  1366.  
  1367.                     sBuffer.ReleaseBuffer();
  1368.                     rVal += sBuffer;
  1369.                     break;
  1370.                   }               
  1371.                 #else   
  1372.                   #ifndef _WINDLL  //only available when statically linked to CRT
  1373.                     case TCHAR('x'):    //Long representation is the same as short representation when not on Win32
  1374.                     {
  1375.                       sBuffer.Empty();                                       
  1376.                       tm tmCDate = GetTM();
  1377.                       strftime(sBuffer.GetBufferSetLength(200), 200, "%x", &tmCDate);
  1378.                       sBuffer.ReleaseBuffer();
  1379.                       rVal += sBuffer;
  1380.                       break;
  1381.                     }                                                            
  1382.                   #endif  
  1383.                 #endif
  1384.                   
  1385.                   case TCHAR('y'):
  1386.                   {
  1387.                     LONG Year = GetYear();
  1388.                     sBuffer.Format(_T("%d"), Get2DigitYear());
  1389.                     rVal += sBuffer;
  1390.                     break;
  1391.                   }
  1392.                   default:
  1393.                   {
  1394.                     rVal += c;
  1395.                     break;
  1396.                   }
  1397.                 }
  1398.               }
  1399.               break;
  1400.             }
  1401.             default:
  1402.             {
  1403.               rVal += c;
  1404.               break;
  1405.             }
  1406.           }
  1407.         }
  1408.       }
  1409.       else
  1410.       {
  1411.         rVal += c;
  1412.       }
  1413.     }
  1414.     sm_sBuffer = rVal;
  1415.   }
  1416.  
  1417.   return sm_sBuffer;
  1418. }
  1419.  
  1420. void CDate::Serialize(CArchive& ar)
  1421. {
  1422.   CObject::Serialize(ar);
  1423.   if(ar.IsStoring())
  1424.   {
  1425.     ar << m_lDays;
  1426.     ar << (WORD) m_bInGregCalendar;
  1427.   }
  1428.   else
  1429.   {
  1430.     ar >> m_lDays;
  1431.     ar >> (WORD&) m_bInGregCalendar;
  1432.   }
  1433. }
  1434.  
  1435. ostream& operator<<(ostream& os, const CDate& date)
  1436. {
  1437.   return os << date.Format();
  1438. }
  1439.  
  1440. CArchive& operator<<(CArchive& ar, CDate& date)
  1441. {
  1442.   ASSERT(ar.IsStoring());
  1443.   date.Serialize(ar);
  1444.   return ar;
  1445. }
  1446.  
  1447. CArchive& operator>>(CArchive& ar, CDate& date)
  1448. {
  1449.   ASSERT(!ar.IsStoring());
  1450.   date.Serialize(ar);
  1451.   return ar;
  1452. }
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460. //CLTimeSpan Implementation
  1461.  
  1462.  
  1463. CLTimeSpan::CLTimeSpan()
  1464. {
  1465.   Set();
  1466. }
  1467.  
  1468. CLTimeSpan::CLTimeSpan(LONG Day, WORD Hour, WORD Minute, 
  1469.                        WORD Second, WORD MilliSecond)
  1470. {
  1471.   Set(Day, Hour, Minute, Second, MilliSecond);
  1472. }
  1473.  
  1474. CLTimeSpan::CLTimeSpan(const CLTimeSpan& lts)
  1475. {
  1476.   m_dSeconds = lts.m_dSeconds;
  1477. }
  1478.  
  1479. CLTimeSpan::CLTimeSpan(const CTimeSpan& ts)
  1480. {
  1481.   Set(ts);
  1482. }
  1483.  
  1484. CLTimeSpan::CLTimeSpan(const CLTimeOfDay& tod)
  1485. {
  1486.   Set(tod);
  1487. }
  1488.       
  1489. #ifdef _WIN32
  1490. CLTimeSpan::CLTimeSpan(const COleDateTimeSpan& oleTimeSpan)
  1491. {
  1492.   Set(oleTimeSpan);
  1493. }                     
  1494. #endif
  1495.  
  1496. CLTimeSpan::CLTimeSpan(const double& Seconds)
  1497. {                                             
  1498.   Set(Seconds);
  1499. }
  1500.  
  1501. CLTimeSpan& CLTimeSpan::Set()
  1502. {                          
  1503.   m_dSeconds = DBL_MAX;
  1504.   return *this;
  1505. }
  1506.  
  1507. CLTimeSpan& CLTimeSpan::Set(LONG Day, WORD Hour, WORD Minute, 
  1508.                             WORD Second, WORD MilliSecond)
  1509.   m_dSeconds = Day*86400.0 +
  1510.                Hour*3600.0 +
  1511.                Minute*60.0 +
  1512.                Second      +
  1513.                MilliSecond/1000.0;
  1514.   return *this;
  1515. }                            
  1516.  
  1517. CLTimeSpan& CLTimeSpan::Set(const CTimeSpan& ts)
  1518. {
  1519.   m_dSeconds = ts.GetTotalSeconds();
  1520.   return *this;
  1521. }
  1522.  
  1523. CLTimeSpan& CLTimeSpan::Set(const CLTimeOfDay& tod)
  1524. {
  1525.   Set(0, tod.GetHour(), tod.GetMinute(), tod.GetSecond(), tod.GetMilliSecond());
  1526.   return *this;
  1527. }
  1528.       
  1529. #ifdef _WIN32
  1530. CLTimeSpan& CLTimeSpan::Set(const COleDateTimeSpan& oleTimeSpan)
  1531. {
  1532.   return Set(oleTimeSpan.GetTotalSeconds());
  1533. }                     
  1534. #endif
  1535.  
  1536. CLTimeSpan& CLTimeSpan::Set(const double& Seconds)
  1537.   if (((Seconds > 0) && (Seconds > ((double)LONG_MAX)*86400)) || 
  1538.       ((Seconds < 0) && (Seconds < ((double)LONG_MIN)*86400)))
  1539.   {
  1540.     if (sm_bDoAsserts)
  1541.       ASSERT(FALSE);
  1542.     Set();
  1543.   }
  1544.   else
  1545.   {
  1546.     double IntPart, fraction;
  1547.     fraction = modf(Seconds, &IntPart);
  1548.     fraction = (floor(fraction*1000 + 0.5))/1000;
  1549.     m_dSeconds = IntPart + fraction;
  1550.   }
  1551.   
  1552.   return *this;
  1553. }
  1554.  
  1555. CLTimeSpan CLTimeSpan::OneCivilYear()
  1556. {
  1557.   return CLTimeSpan(365, 6, 0, 0, 0);
  1558. }
  1559.  
  1560. CLTimeSpan CLTimeSpan::OneDay()
  1561. {
  1562.   return CLTimeSpan(1, 0, 0, 0, 0);
  1563. }
  1564.  
  1565. CLTimeSpan CLTimeSpan::OneHour()
  1566. {
  1567.   return CLTimeSpan(0, 1, 0, 0, 0);
  1568. }
  1569.  
  1570. CLTimeSpan CLTimeSpan::OneMinute()
  1571. {
  1572.   return CLTimeSpan(0, 0, 1, 0, 0);
  1573. }
  1574.  
  1575. CLTimeSpan CLTimeSpan::OneSecond()
  1576. {
  1577.   return CLTimeSpan(0, 0, 0, 1, 0);
  1578. }
  1579.  
  1580. CLTimeSpan CLTimeSpan::OneMilliSecond()
  1581. {
  1582.   return CLTimeSpan(0, 0, 0, 0, 1);
  1583. }
  1584.  
  1585. void CLTimeSpan::SetDefaultFormat(const CString& Format)
  1586. {
  1587.   sm_sDefaultFormat = Format;
  1588. }
  1589.  
  1590. CString& CLTimeSpan::GetDefaultFormat()
  1591. {
  1592.   return sm_sDefaultFormat;
  1593. }
  1594.  
  1595. #ifdef _DEBUG
  1596. BOOL CLTimeSpan::SetDoConstructorAsserts(BOOL bDoAsserts)
  1597. {
  1598.   BOOL bOldDoAsserts = sm_bDoAsserts;
  1599.   sm_bDoAsserts = bDoAsserts;
  1600.   return bOldDoAsserts;
  1601. }
  1602. #endif                     
  1603.  
  1604. void CLTimeSpan::ClearStatics()
  1605. {
  1606.   sm_sBuffer.Empty();
  1607.   sm_sDefaultFormat.Empty();
  1608. }
  1609.                                  
  1610. LONG CLTimeSpan::GetTotalDays() const
  1611. {
  1612.   AssertValid();
  1613.   return (LONG) (m_dSeconds/86400);
  1614. }
  1615.  
  1616. WORD CLTimeSpan::GetHours() const
  1617. {
  1618.   AssertValid();
  1619.   return (WORD) ((fabs(m_dSeconds) - 86400L*fabs(GetTotalDays()))/3600);
  1620. }
  1621.  
  1622. WORD CLTimeSpan::GetMinutes() const
  1623. {
  1624.   AssertValid();
  1625.   return (WORD) ((fabs(m_dSeconds) - 86400L*fabs(GetTotalDays()) - 3600L*GetHours())/60);
  1626. }
  1627.  
  1628. WORD CLTimeSpan::GetSeconds() const
  1629. {
  1630.   AssertValid();
  1631.   return (WORD) (fabs(m_dSeconds) - 86400L*fabs(GetTotalDays()) - 3600L*GetHours() - 60*GetMinutes());
  1632. }                             
  1633.  
  1634. WORD CLTimeSpan::GetMilliSeconds() const
  1635. {
  1636.   AssertValid();
  1637.   double IntPart, fraction;
  1638.   fraction = modf(m_dSeconds, &IntPart);
  1639.   return (WORD) labs(((LONG) (floor(fraction*1000 + 0.5))));
  1640. }
  1641.  
  1642. BOOL CLTimeSpan::IsValid() const
  1643. {
  1644.   return (m_dSeconds != DBL_MAX);
  1645. }
  1646.  
  1647. CLTimeSpan& CLTimeSpan::Negate()
  1648. {
  1649.   AssertValid();
  1650.   m_dSeconds = (-m_dSeconds);
  1651.   return *this;
  1652. }
  1653.  
  1654. BOOL CLTimeSpan::IsPositiveSpan() const
  1655. {
  1656.   AssertValid();
  1657.   return (m_dSeconds >= 0);
  1658. }
  1659.  
  1660. double CLTimeSpan::SecondsAsDouble() const
  1661. {
  1662.   AssertValid();
  1663.   return m_dSeconds;
  1664. }
  1665.  
  1666. BOOL CLTimeSpan::operator==(const CLTimeSpan& TimeSpan) const
  1667. {
  1668.   AssertValid();
  1669.   return (m_dSeconds == TimeSpan.m_dSeconds);
  1670. }
  1671.  
  1672. BOOL CLTimeSpan::operator>(const CLTimeSpan& TimeSpan) const
  1673. {
  1674.   AssertValid();
  1675.   return (m_dSeconds > TimeSpan.m_dSeconds);
  1676. }
  1677.  
  1678. BOOL CLTimeSpan::operator>=(const CLTimeSpan& TimeSpan) const
  1679. {
  1680.   AssertValid();
  1681.   return (m_dSeconds >= TimeSpan.m_dSeconds);
  1682. }
  1683.  
  1684. BOOL CLTimeSpan::operator<(const CLTimeSpan& TimeSpan) const
  1685. {
  1686.   AssertValid();
  1687.   return (m_dSeconds < TimeSpan.m_dSeconds);
  1688. }
  1689.  
  1690. BOOL CLTimeSpan::operator<=(const CLTimeSpan& TimeSpan) const
  1691. {
  1692.   AssertValid();
  1693.   return (m_dSeconds <= TimeSpan.m_dSeconds);
  1694. }
  1695.  
  1696. BOOL CLTimeSpan::operator!=(const CLTimeSpan& TimeSpan) const
  1697. {
  1698.   AssertValid();
  1699.   return (m_dSeconds != TimeSpan.m_dSeconds);
  1700. }
  1701.                                  
  1702. CLTimeSpan& CLTimeSpan::operator=(const CLTimeSpan& TimeSpan)
  1703.   m_dSeconds = TimeSpan.m_dSeconds;
  1704.   return *this;
  1705. }
  1706.  
  1707. CLTimeSpan CLTimeSpan::operator+(const CLTimeSpan& TimeSpan) const
  1708. {
  1709.   AssertValid();
  1710.   TimeSpan.AssertValid();
  1711.   double rVal = m_dSeconds + TimeSpan.m_dSeconds;
  1712.   return CLTimeSpan(rVal);
  1713. }
  1714.  
  1715. CLTimeSpan CLTimeSpan::operator-(const CLTimeSpan& TimeSpan) const
  1716. {
  1717.   AssertValid();
  1718.   TimeSpan.AssertValid();
  1719.   double rVal = m_dSeconds - TimeSpan.m_dSeconds;
  1720.   return rVal;
  1721. }
  1722.  
  1723. CLTimeSpan& CLTimeSpan::operator+=(CLTimeSpan& TimeSpan)
  1724. {
  1725.   *this = *this + TimeSpan;
  1726.   return *this;
  1727. }
  1728.  
  1729. CLTimeSpan& CLTimeSpan::operator-=(CLTimeSpan& TimeSpan)
  1730. {
  1731.   *this = *this - TimeSpan;
  1732.   return *this;
  1733. }
  1734.  
  1735. CLTimeSpan operator-(const CLTimeSpan& TimeSpan)
  1736. {
  1737.   CLTimeSpan rVal(TimeSpan);
  1738.   return rVal.Negate();
  1739. }
  1740.  
  1741. CLTimeSpan CLTimeSpan::operator*(WORD Multiplier) const
  1742. {
  1743.   return ::operator*(Multiplier, *this);
  1744. }
  1745.  
  1746. CLTimeSpan operator*(WORD Multiplier, const CLTimeSpan& TimeSpan)
  1747. {
  1748.   TimeSpan.AssertValid();
  1749.   double rVal = TimeSpan.m_dSeconds * Multiplier;
  1750.   return CLTimeSpan(rVal);
  1751. }
  1752.  
  1753. CLTimeSpan CLTimeSpan::operator/(WORD divisor) const
  1754. {
  1755.   AssertValid();
  1756.   double rVal = m_dSeconds / ((double) divisor);
  1757.   return CLTimeSpan(rVal);
  1758. }
  1759.  
  1760. CLTimeSpan& CLTimeSpan::operator*=(WORD Multiplier)
  1761. {
  1762.   *this = operator*(Multiplier);
  1763.   return *this;
  1764. }
  1765.  
  1766. CLTimeSpan& CLTimeSpan::operator/=(WORD Divisor)
  1767. {
  1768.   *this = operator/(Divisor);
  1769.   return *this;
  1770. }
  1771.  
  1772. #ifdef _DEBUG
  1773. void CLTimeSpan::AssertValid() const
  1774. {
  1775.   CObject::AssertValid();
  1776.   ASSERT(IsValid());
  1777. }
  1778. #endif
  1779.  
  1780. #ifdef _DEBUG
  1781. void CLTimeSpan::Dump(CDumpContext& dc) const
  1782. {
  1783.   CObject::Dump(dc);
  1784.   dc << Format() << _T("\n");
  1785. }
  1786. #endif
  1787.  
  1788. /*    //The Following Format parameters are supported        
  1789. %D    Total days in this CLTimeSpan
  1790. %H    Hours in this CLTimeSpan (00 - 23)
  1791. %M    Minutes in the current hour in this CLTimeSpan (00 - 59)
  1792. %S    Seconds in the current minute in this CLTimeSpan (00 - 59)
  1793. %F    MilliSeconds in the current second in this CLTimeSpan (000 - 999)
  1794. %%    Percent sign
  1795. %#H, %#M, %#S  Remove leading zeros (if any).
  1796. */
  1797. CString& CLTimeSpan::Format(const CString& sFormat) const
  1798.   if (!IsValid())
  1799.     sm_sBuffer.Empty();
  1800.   else
  1801.   {
  1802.     CString sBuffer;
  1803.     CString rVal;
  1804.     sm_sBuffer.Empty();
  1805.     int sFmtLength = sFormat.GetLength();
  1806.  
  1807.     for (int i=0; i<sFmtLength; i++)
  1808.     {
  1809.       TCHAR c = sFormat.GetAt(i);
  1810.       if (c == TCHAR('%'))
  1811.       {
  1812.         ++i;
  1813.         if (i < sFmtLength)
  1814.         {
  1815.           c = sFormat.GetAt(i);
  1816.           switch (c)
  1817.           {
  1818.             case TCHAR('D'):
  1819.             {
  1820.               LONG Days = GetTotalDays();
  1821.               sBuffer.Format(_T("%ld"), Days);
  1822.               if (IsPositiveSpan())
  1823.                 rVal += _T("+");
  1824.               else if (Days == 0) //handle neagtive 0
  1825.                 rVal += _T("-");
  1826.               rVal += sBuffer;
  1827.               break;
  1828.             }
  1829.             case TCHAR('H'):
  1830.             {
  1831.               sBuffer.Format(_T("%.02d"), GetHours());
  1832.               rVal += sBuffer;
  1833.               break;
  1834.             }
  1835.             case TCHAR('M'):
  1836.             {
  1837.               sBuffer.Format(_T("%.02d"), GetMinutes());
  1838.               rVal += sBuffer;
  1839.               break;
  1840.             }
  1841.             case TCHAR('S'):
  1842.             {
  1843.               sBuffer.Format(_T("%.02d"), GetSeconds());
  1844.               rVal += sBuffer;
  1845.               break;
  1846.             }
  1847.             case TCHAR('F'):
  1848.             {
  1849.               sBuffer.Format(_T("%.03d"), GetMilliSeconds());
  1850.               rVal += sBuffer;
  1851.               break;
  1852.             }
  1853.             case TCHAR('#'):
  1854.             {
  1855.               if (i < sFmtLength)
  1856.               {
  1857.                 ++i;
  1858.                 c = sFormat.GetAt(i);
  1859.                 switch (c)
  1860.                 {
  1861.                   case TCHAR('H'):
  1862.                   {
  1863.                     sBuffer.Format(_T("%d"), GetHours());
  1864.                     rVal += sBuffer;
  1865.                     break;
  1866.                   }
  1867.                   case TCHAR('M'):
  1868.                   {
  1869.                     sBuffer.Format(_T("%d"), GetMinutes());
  1870.                     rVal += sBuffer;
  1871.                     break;
  1872.                   }
  1873.                   case TCHAR('S'):
  1874.                   {
  1875.                     sBuffer.Format(_T("%d"), GetSeconds());
  1876.                     rVal += sBuffer;
  1877.                     break;
  1878.                   }
  1879.                   default:
  1880.                   {
  1881.                     rVal += c;
  1882.                     break;
  1883.                   }
  1884.                 }
  1885.               break;
  1886.               }
  1887.             }
  1888.             default:
  1889.             {
  1890.               rVal += c;
  1891.               break;
  1892.             }
  1893.           }
  1894.         }
  1895.       }
  1896.       else
  1897.       {
  1898.         rVal += c;
  1899.       }
  1900.     }
  1901.     sm_sBuffer = rVal;
  1902.   }
  1903.   
  1904.   return sm_sBuffer;
  1905. }
  1906.  
  1907. void CLTimeSpan::Serialize(CArchive& ar)
  1908. {
  1909.   CObject::Serialize(ar);
  1910.   if(ar.IsStoring())
  1911.   {
  1912.     ar << m_dSeconds;
  1913.   }
  1914.   else
  1915.   {
  1916.     ar >> m_dSeconds;
  1917.   }
  1918. }
  1919.  
  1920. ostream& operator<<(ostream &os, const CLTimeSpan& TimeSpan)
  1921. {
  1922.   return os << TimeSpan.Format();
  1923. }                  
  1924.  
  1925. CArchive& operator<<(CArchive& ar, CLTimeSpan& TimeSpan)
  1926. {
  1927.   ASSERT(ar.IsStoring());
  1928.   TimeSpan.Serialize(ar);
  1929.   return ar;
  1930. }
  1931.                
  1932. CArchive& operator>>(CArchive& ar, CLTimeSpan& TimeSpan)
  1933. {
  1934.   ASSERT(!ar.IsStoring());
  1935.   TimeSpan.Serialize(ar);
  1936.   return ar;
  1937. }
  1938.  
  1939.  
  1940.  
  1941.  
  1942.  
  1943.  
  1944. //CLTimeOfDay Implementation
  1945.  
  1946. CLTimeOfDay::CLTimeOfDay()
  1947. {
  1948.   Set();
  1949. }
  1950.  
  1951. CLTimeOfDay::CLTimeOfDay(WORD Hour, WORD Minute, 
  1952.            WORD Second, WORD MilliSecond)
  1953. {
  1954.   Set(Hour, Minute, Second, MilliSecond);
  1955. }    
  1956.  
  1957. CLTimeOfDay::CLTimeOfDay(const double& Seconds)
  1958. {
  1959.   Set(Seconds);
  1960. }    
  1961.  
  1962. CLTimeOfDay::CLTimeOfDay(const SYSTEMTIME& st)
  1963. {        
  1964.   Set(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  1965. }
  1966.            
  1967. CLTimeOfDay::CLTimeOfDay(const CLTimeOfDay& ltod)
  1968. {
  1969.   m_dwTotalSeconds = ltod.m_dwTotalSeconds;
  1970.   m_wMilliSeconds = ltod.m_wMilliSeconds;
  1971. }                                
  1972.  
  1973. CLTimeOfDay::CLTimeOfDay(DWORD TotalSeconds, WORD MilliSecond)
  1974. {
  1975.   Set(TotalSeconds, MilliSecond);
  1976. }                                
  1977.  
  1978.  
  1979. CLTimeOfDay& CLTimeOfDay::Set()
  1980. {
  1981.   m_dwTotalSeconds = 86400; //an illegal value
  1982.   m_wMilliSeconds = 0;
  1983.   return *this;
  1984. }
  1985.  
  1986. CLTimeOfDay& CLTimeOfDay::Set(const double& Seconds)
  1987. {
  1988.   if (Seconds < 0)
  1989.   {
  1990.     if (sm_bDoAsserts)
  1991.       ASSERT(FALSE);
  1992.     Set();
  1993.     return *this;
  1994.   }
  1995.   
  1996.   double FracPart, IntPart;
  1997.   FracPart = modf(Seconds, &IntPart);
  1998.   DWORD dwSeconds = (DWORD) IntPart;
  1999.   WORD wMilliSeconds = (WORD) (FracPart*1000 + 0.5);
  2000.   Set(dwSeconds, wMilliSeconds);
  2001.   return *this;
  2002. }
  2003.  
  2004. CLTimeOfDay& CLTimeOfDay::Set(WORD Hour, WORD Minute,
  2005.                 WORD Second, WORD MilliSecond)
  2006. {
  2007.   WORD AdditionalSeconds = (WORD) ((MilliSecond/1000)*1000);
  2008.   LONG lSeconds = Minute + 60L*Hour;
  2009.   lSeconds *= 60;
  2010.   lSeconds += Second + AdditionalSeconds;
  2011.   m_dwTotalSeconds = lSeconds;
  2012.   if (m_dwTotalSeconds >= 86400L)
  2013.   {
  2014.     if (sm_bDoAsserts)
  2015.       ASSERT(FALSE);
  2016.     Set();
  2017.     return *this;
  2018.   }
  2019.   m_wMilliSeconds = (WORD) (MilliSecond - (AdditionalSeconds*1000));
  2020.   return *this;  
  2021. }                
  2022.                                  
  2023. CLTimeOfDay& CLTimeOfDay::Set(DWORD TotalSeconds, WORD MilliSecond)
  2024. {
  2025.   WORD AdditionalSeconds = (WORD) ((MilliSecond/1000)*1000);
  2026.   m_dwTotalSeconds = TotalSeconds + AdditionalSeconds;
  2027.   if (m_dwTotalSeconds >= 86400)
  2028.   {
  2029.     if (sm_bDoAsserts)
  2030.       ASSERT(FALSE);
  2031.     Set();
  2032.     return *this;
  2033.   }
  2034.   m_wMilliSeconds = (WORD) (MilliSecond - (AdditionalSeconds*1000));
  2035.   return *this;  
  2036. }
  2037.                                  
  2038. CLTimeOfDay CLTimeOfDay::CurrentTimeOfDay(TimeFrame tf)
  2039.   #ifdef _WIN32
  2040.     SYSTEMTIME st;                                
  2041.     switch (tf)
  2042.     {    
  2043.       case UTC:
  2044.         ::GetSystemTime(&st); 
  2045.         break;
  2046.       case LOCAL:
  2047.         ::GetLocalTime(&st); 
  2048.         break;   
  2049.       case ET:
  2050.         ASSERT(FALSE);
  2051.         break;
  2052.       default: ASSERT(FALSE);
  2053.     }    
  2054.         
  2055.     return CLTimeOfDay(st);
  2056.   #else                                        
  2057.     time_t csecs = time(NULL);
  2058.     tm* ct = localtime(&csecs);
  2059.     CLTimeOfDay ctime((WORD) (ct->tm_hour), (WORD) (ct->tm_min), (WORD) (ct->tm_sec), 0);
  2060.     switch (tf)
  2061.     {
  2062.       case UTC:
  2063.         TIME_ZONE_INFORMATION tzi;
  2064.         GetTimeZoneInformation(&tzi);
  2065.         ctime -= CLTimeSpan((double) tzi.Bias);
  2066.         break;
  2067.       case LOCAL:                         
  2068.         {
  2069.         // nothing required;        
  2070.         break;
  2071.         }
  2072.       case ET:
  2073.         ASSERT(FALSE);
  2074.         break;
  2075.       default: ASSERT(FALSE);      
  2076.     }
  2077.   
  2078.     return ctime;
  2079.   #endif
  2080. }
  2081.                                  
  2082. CLTimeOfDay CLTimeOfDay::Midnight()
  2083. {
  2084.   return CLTimeOfDay(0, 0, 0, 0);
  2085. }
  2086.  
  2087. CLTimeOfDay CLTimeOfDay::Midday()
  2088. {
  2089.   return CLTimeOfDay(12, 0, 0, 0);
  2090. }
  2091.  
  2092. void CLTimeOfDay::SetDefaultFormat(const CString& Format)
  2093. {
  2094.   sm_sDefaultFormat = Format;
  2095. }
  2096.  
  2097. CString& CLTimeOfDay::GetDefaultFormat()
  2098. {
  2099.   return sm_sDefaultFormat;
  2100. }
  2101.  
  2102. #ifdef _DEBUG
  2103. BOOL CLTimeOfDay::SetDoConstructorAsserts(BOOL bDoAsserts)
  2104. {
  2105.   BOOL bOldDoAsserts = sm_bDoAsserts;
  2106.   sm_bDoAsserts = bDoAsserts;
  2107.   return bOldDoAsserts;
  2108. }
  2109. #endif                 
  2110.  
  2111. void CLTimeOfDay::ClearStatics()
  2112. {
  2113.   sm_sBuffer.Empty();
  2114.   sm_sDefaultFormat.Empty();
  2115. }
  2116.                                  
  2117. WORD CLTimeOfDay::GetHour() const
  2118. {
  2119.   AssertValid();
  2120.   return (WORD) (m_dwTotalSeconds/3600L);
  2121. }
  2122.  
  2123. WORD CLTimeOfDay::GetMinute() const
  2124. {
  2125.   AssertValid();
  2126.   return (WORD) ((m_dwTotalSeconds - (GetHour()*3600L))/60);
  2127. }
  2128.  
  2129. DWORD CLTimeOfDay::GetTotalSeconds() const
  2130. {
  2131.   AssertValid();
  2132.   return m_dwTotalSeconds;
  2133. }
  2134.  
  2135. WORD CLTimeOfDay::GetSecond() const
  2136. {
  2137.   AssertValid();
  2138.   return (WORD) (m_dwTotalSeconds - (60L * (GetMinute() + (60L*GetHour()))));
  2139. }                                                                
  2140.  
  2141. WORD CLTimeOfDay::GetMilliSecond() const
  2142. {
  2143.   AssertValid();
  2144.   return m_wMilliSeconds;
  2145. }
  2146.  
  2147. WORD CLTimeOfDay::GetAMPMHour() const
  2148. {
  2149.   AssertValid();
  2150.   WORD wHour = GetHour();
  2151.   if (wHour > 12)
  2152.     wHour -= 12;
  2153.   return wHour;
  2154. }                             
  2155.  
  2156. CString& CLTimeOfDay::GetAMPMString() const
  2157. {
  2158.   AssertValid();
  2159.   int nStringID;
  2160.   if (GetHour() > 12)
  2161.     nStringID = IDS_PM;
  2162.   else
  2163.     nStringID = IDS_AM;
  2164.  
  2165.   if (!sm_sBuffer.LoadString(nStringID))
  2166.     ASSERT(FALSE);
  2167.   return sm_sBuffer;
  2168. }
  2169.  
  2170. BOOL CLTimeOfDay::IsValid() const
  2171. {                  
  2172.   if (m_dwTotalSeconds >= 86400) 
  2173.     return FALSE;
  2174.   else
  2175.     return TRUE;  
  2176. }
  2177.  
  2178. ULARGE_INTEGER CLTimeOfDay::Collate() const
  2179. {
  2180.   AssertValid();
  2181.   ULARGE_INTEGER rVal;
  2182.   rVal.LowPart = m_wMilliSeconds;
  2183.   rVal.HighPart = (GetHour()*10000L) + (GetMinute()*100L) + GetSecond();
  2184.   return rVal;
  2185. }
  2186.  
  2187. SYSTEMTIME CLTimeOfDay::GetSYSTEMTIME() const
  2188. {
  2189.   AssertValid();
  2190.   SYSTEMTIME st;
  2191.  
  2192.   st.wYear=0;
  2193.   st.wMonth=0;
  2194.   st.wDayOfWeek=0;
  2195.   st.wDay=0;
  2196.   st.wHour = GetHour();
  2197.   st.wMinute = GetMinute();
  2198.   st.wSecond = GetSecond();
  2199.   st.wMilliseconds = GetMilliSecond();
  2200.   return st;
  2201. }
  2202.  
  2203. tm CLTimeOfDay::GetTM() const
  2204. {
  2205.   AssertValid();
  2206.   tm rVal;
  2207.   
  2208.   rVal.tm_hour  = GetHour();
  2209.   rVal.tm_min   = GetMinute();
  2210.   rVal.tm_sec   = GetSecond();
  2211.   rVal.tm_mday  = 0;
  2212.   rVal.tm_mon   = 0;
  2213.   rVal.tm_year  = 0;
  2214.   rVal.tm_wday  = 0;
  2215.   rVal.tm_yday  = 0;
  2216.   rVal.tm_isdst = 0;
  2217.               
  2218.   return rVal;
  2219. }
  2220.  
  2221. double CLTimeOfDay::SecondsAsDouble() const
  2222. {
  2223.   AssertValid();
  2224.   return m_dwTotalSeconds + m_wMilliSeconds/1000.0;
  2225. }
  2226.  
  2227.  
  2228. CLTimeOfDay& CLTimeOfDay::operator=(const CLTimeOfDay& Tod)
  2229. {               
  2230.   m_dwTotalSeconds = Tod.m_dwTotalSeconds;
  2231.   m_wMilliSeconds = Tod.m_wMilliSeconds;
  2232.   return *this;
  2233. }
  2234.  
  2235. CLTimeOfDay CLTimeOfDay::operator+(const CLTimeSpan& TimeSpan) const
  2236. {
  2237.   AssertValid();
  2238.   CLTimeSpan t = CLTimeSpan(*this) + CLTimeSpan(0, TimeSpan.GetHours(), TimeSpan.GetMinutes(),
  2239.                             TimeSpan.GetSeconds(),  TimeSpan.GetMilliSeconds());
  2240.   return CLTimeOfDay(t.GetHours(), t.GetMinutes(), t.GetSeconds(), t.GetMilliSeconds());
  2241. }
  2242.  
  2243. CLTimeOfDay CLTimeOfDay::operator-(const CLTimeSpan& TimeSpan) const
  2244. {
  2245.   AssertValid();
  2246.   CLTimeSpan t = CLTimeSpan::OneDay() + CLTimeSpan(*this) - 
  2247.                  CLTimeSpan(0, TimeSpan.GetHours(), TimeSpan.GetMinutes(),
  2248.                             TimeSpan.GetSeconds(),  TimeSpan.GetMilliSeconds());
  2249.   //1 Day is used to ensure result "t" does not go negative
  2250.   return CLTimeOfDay(t.GetHours(), t.GetMinutes(), t.GetSeconds(), t.GetMilliSeconds());
  2251. }
  2252.  
  2253. CLTimeOfDay& CLTimeOfDay::operator+=(CLTimeSpan& TimeSpan)
  2254. {
  2255.   *this = *this + TimeSpan;
  2256.   return *this;
  2257. }
  2258.  
  2259. CLTimeOfDay& CLTimeOfDay::operator-=(CLTimeSpan& TimeSpan)
  2260. {
  2261.   *this = *this - TimeSpan;
  2262.   return *this;
  2263. }
  2264.  
  2265. BOOL CLTimeOfDay::operator==(const CLTimeOfDay& Tod) const
  2266. {
  2267.   AssertValid();
  2268.   if ((m_wMilliSeconds == Tod.m_wMilliSeconds) &&
  2269.       (m_dwTotalSeconds == Tod.m_dwTotalSeconds))
  2270.     return TRUE;
  2271.   else
  2272.     return FALSE;    
  2273. }
  2274.  
  2275. BOOL CLTimeOfDay::operator>(const CLTimeOfDay& Tod) const
  2276. {               
  2277.   AssertValid();
  2278.   if (m_dwTotalSeconds == Tod.m_dwTotalSeconds)
  2279.     return (m_wMilliSeconds > Tod.m_wMilliSeconds);
  2280.   else
  2281.     return (m_dwTotalSeconds > Tod.m_dwTotalSeconds);
  2282. }
  2283.  
  2284. BOOL CLTimeOfDay::operator>=(const CLTimeOfDay& Tod) const
  2285. {               
  2286.   AssertValid();
  2287.   if (m_dwTotalSeconds == Tod.m_dwTotalSeconds)
  2288.     return (m_wMilliSeconds >= Tod.m_wMilliSeconds);
  2289.   else
  2290.     return (m_dwTotalSeconds >= Tod.m_dwTotalSeconds);
  2291. }
  2292.  
  2293. BOOL CLTimeOfDay::operator<(const CLTimeOfDay& Tod) const
  2294. {             
  2295.   AssertValid();
  2296.   if (m_dwTotalSeconds == Tod.m_dwTotalSeconds)
  2297.     return (m_wMilliSeconds < Tod.m_wMilliSeconds);
  2298.   else
  2299.     return (m_dwTotalSeconds < Tod.m_dwTotalSeconds);
  2300. }
  2301.  
  2302. BOOL CLTimeOfDay::operator<=(const CLTimeOfDay& Tod) const
  2303. {
  2304.   AssertValid();
  2305.   if (m_dwTotalSeconds == Tod.m_dwTotalSeconds)
  2306.     return (m_wMilliSeconds <= Tod.m_wMilliSeconds);
  2307.   else
  2308.     return (m_dwTotalSeconds <= Tod.m_dwTotalSeconds);
  2309. }
  2310.  
  2311. BOOL CLTimeOfDay::operator!=(const CLTimeOfDay& Tod) const
  2312. {               
  2313.   AssertValid();                  
  2314.   return !operator==(Tod);
  2315. }
  2316.  
  2317. #ifdef _DEBUG
  2318. void CLTimeOfDay::AssertValid() const
  2319. {
  2320.   CObject::AssertValid();
  2321.   ASSERT(IsValid());
  2322. }
  2323. #endif
  2324.  
  2325. #ifdef _DEBUG
  2326. void CLTimeOfDay::Dump(CDumpContext& dc) const
  2327. {
  2328.   CObject::Dump(dc);
  2329.   dc << Format() << _T("\n");
  2330. }
  2331. #endif                       
  2332.  
  2333. /*    //The Following Format parameters are supported        
  2334.  
  2335. %H    Hours in the current day
  2336. %M    Minutes in the current hour
  2337. %h    12 Hour format Hours in this CLTimeSpan (00 - 12)
  2338. %P    AM / PM indicator
  2339. %S    Seconds in the current minute
  2340. %F    MilliSeconds in the current second
  2341. %%    Percent sign       
  2342. %x    Time Of Day representation for current locale        
  2343. %#H, %#h, %#M, %#S  Remove leading zeros (if any).
  2344. */
  2345. CString& CLTimeOfDay::Format(const CString& sFormat) const
  2346.   if (!IsValid())
  2347.     sm_sBuffer.Empty();
  2348.   else
  2349.   {
  2350.     CString sBuffer;
  2351.     sm_sBuffer.Empty();
  2352.     CString rVal;
  2353.     int sFmtLength = sFormat.GetLength();
  2354.  
  2355.     for (int i=0; i<sFmtLength; i++)
  2356.     {
  2357.       TCHAR c = sFormat.GetAt(i);
  2358.       if (c == TCHAR('%'))
  2359.       {
  2360.         ++i;
  2361.         if (i < sFmtLength)
  2362.         {
  2363.           c = sFormat.GetAt(i);
  2364.           switch (c)
  2365.           {
  2366.             case TCHAR('H'):
  2367.             {
  2368.               sBuffer.Format(_T("%.02d"), GetHour());
  2369.               rVal += sBuffer;
  2370.               break;
  2371.             }
  2372.             case TCHAR('M'):
  2373.             {
  2374.               sBuffer.Format(_T("%.02d"), GetMinute());
  2375.               rVal += sBuffer;
  2376.               break;
  2377.             }
  2378.             case TCHAR('h'):
  2379.             {
  2380.               sBuffer.Format(_T("%.02d"), GetAMPMHour());
  2381.               rVal += sBuffer;
  2382.               break;
  2383.             }
  2384.             case TCHAR('P'):
  2385.             {
  2386.               rVal += GetAMPMString();
  2387.               break;
  2388.             }
  2389.             case TCHAR('S'):
  2390.             {
  2391.               sBuffer.Format(_T("%.02d"), GetSecond());
  2392.               rVal += sBuffer;
  2393.               break;
  2394.             }
  2395.             case TCHAR('F'):
  2396.             {
  2397.               sBuffer.Format(_T("%.03d"), GetMilliSecond());
  2398.               rVal += sBuffer;
  2399.               break;                                              
  2400.             }                                                     
  2401.             
  2402.           #ifdef _WIN32
  2403.             case TCHAR('x'):                                      
  2404.             {
  2405.               sBuffer.Empty();
  2406.               SYSTEMTIME st = GetSYSTEMTIME();
  2407.               int Res = ::GetTimeFormat(LOCALE_USER_DEFAULT,
  2408.                                       LOCALE_NOUSEROVERRIDE,
  2409.                                       &st,
  2410.                                       NULL,
  2411.                                       sBuffer.GetBufferSetLength(100),
  2412.                                       100); 
  2413.               if (Res == 0)
  2414.                 TRACE1("GetDateFormat() Failed in CLTimeSpan::Format(), GetLastError() returned %ul\n", ::GetLastError());
  2415.               sBuffer.ReleaseBuffer();
  2416.               rVal += sBuffer;
  2417.               break;
  2418.             }
  2419.           #endif
  2420.             
  2421.             case TCHAR('#'):
  2422.             {
  2423.               if (i < sFmtLength)
  2424.               {
  2425.                 ++i;
  2426.                 c = sFormat.GetAt(i);
  2427.                 switch (c)
  2428.                 {
  2429.                   case TCHAR('H'):
  2430.                   {
  2431.                     sBuffer.Format(_T("%d"), GetHour());
  2432.                     rVal += sBuffer;
  2433.                     break;
  2434.                   }
  2435.                   case TCHAR('h'):
  2436.                   {
  2437.                     sBuffer.Format(_T("%d"), GetAMPMHour());
  2438.                     rVal += sBuffer;
  2439.                     break;
  2440.                   }
  2441.                   case TCHAR('M'):
  2442.                   {
  2443.                     sBuffer.Format(_T("%d"), GetMinute());
  2444.                     rVal += sBuffer;
  2445.                     break;
  2446.                   }
  2447.                   case TCHAR('S'):
  2448.                   {
  2449.                     sBuffer.Format(_T("%d"), GetSecond());
  2450.                     rVal += sBuffer;
  2451.                     break;
  2452.                   }
  2453.                   default:
  2454.                   {
  2455.                     rVal += c;
  2456.                     break;
  2457.                   }
  2458.                 }
  2459.               }
  2460.               break;
  2461.             }
  2462.             default:
  2463.             {
  2464.               rVal += c;
  2465.               break;
  2466.             }
  2467.           }
  2468.         }
  2469.       }
  2470.       else
  2471.       {
  2472.         rVal += c;
  2473.       }
  2474.     }
  2475.     sm_sBuffer = rVal;
  2476.   }
  2477.   return sm_sBuffer;
  2478. }
  2479.  
  2480.  
  2481. void CLTimeOfDay::Serialize(CArchive& ar)
  2482. {
  2483.   CObject::Serialize(ar);
  2484.   if(ar.IsStoring())
  2485.   {
  2486.     ar << m_dwTotalSeconds;
  2487.     ar << m_wMilliSeconds;
  2488.   }
  2489.   else
  2490.   {
  2491.     ar >> m_dwTotalSeconds;
  2492.     ar >> m_wMilliSeconds;
  2493.   }
  2494. }
  2495.  
  2496. ostream& operator<<(ostream &os, const CLTimeOfDay &TimeOfDay)
  2497. {
  2498.   return os << TimeOfDay.Format();
  2499. }                       
  2500.  
  2501. CArchive& operator<<(CArchive& ar, CLTimeOfDay &TimeOfDay)
  2502. {
  2503.   ASSERT(ar.IsStoring());
  2504.   TimeOfDay.Serialize(ar);
  2505.   return ar;
  2506. }
  2507.  
  2508. CArchive& operator>>(CArchive& ar, CLTimeOfDay &TimeOfDay)
  2509. {
  2510.   ASSERT(!ar.IsStoring());
  2511.   TimeOfDay.Serialize(ar);
  2512.   return ar;
  2513. }
  2514.  
  2515.  
  2516.  
  2517.  
  2518.  
  2519.  
  2520. //CLDate implementation
  2521.  
  2522.  
  2523. CLDate::CLDate()
  2524. {
  2525.   Set();
  2526. }
  2527.   
  2528. CLDate::CLDate(LONG Year, WORD Month, WORD Day, 
  2529.                WORD Hour, WORD Minute, WORD Second,
  2530.                WORD MilliSecond, TimeFrame tf)
  2531. {
  2532.   Set(Year, Month, Day, Hour, Minute, Second, MilliSecond, tf);
  2533. }                                            
  2534.  
  2535.  
  2536. CLDate::CLDate(const SYSTEMTIME& st, TimeFrame tf, BOOL bUseDayOfWeek)
  2537.   Set(st, tf, bUseDayOfWeek);
  2538.  
  2539.  
  2540. CLDate::CLDate(LONG Year, WORD Month, WORD WeekOfMonth,
  2541.                WORD DayOfWeek, WORD Hour, WORD Minute, WORD Second,
  2542.                WORD MilliSecond, TimeFrame tf)
  2543. {
  2544.   Set(Year, Month, WeekOfMonth, DayOfWeek, Hour, Minute, Second, MilliSecond, tf);
  2545. }
  2546.                
  2547. CLDate::CLDate(LONG Days, CDate::DateEpoch e, WORD Hour, WORD Minute,
  2548.                WORD Second, WORD MilliSecond, TimeFrame tf)
  2549. {
  2550.   Set(Days, e, Hour, Minute, Second, MilliSecond, tf);
  2551.  
  2552.  
  2553. CLDate::CLDate(const CDate& Date, const CLTimeOfDay& Tod, TimeFrame tf)
  2554.   Set(Date, Tod, tf);
  2555. }
  2556.  
  2557. CLDate::CLDate(const CLDate& ld)
  2558. {                                 
  2559.   m_dSeconds = ld.m_dSeconds;
  2560.   m_TimeFrame = ld.m_TimeFrame;
  2561. }
  2562.  
  2563. CLDate::CLDate(const CTime& ct)
  2564. {
  2565.   Set(ct);
  2566. }
  2567.       
  2568. #ifdef _WIN32
  2569. CLDate::CLDate(const COleDateTime& oleTime, TimeFrame tf)
  2570. {
  2571.   Set(oleTime, tf);
  2572. }                     
  2573. #endif
  2574.  
  2575. CLDate& CLDate::Set()
  2576. {
  2577.   m_dSeconds = DBL_MAX;
  2578.   return *this;
  2579. }
  2580.  
  2581. CLDate& CLDate::Set(LONG Year, WORD Month, WORD Day,
  2582.                     WORD Hour, WORD Minute, WORD Second,
  2583.                     WORD MilliSecond, TimeFrame tf)
  2584. {              
  2585.   m_TimeFrame = tf;
  2586.  
  2587.   CDate Date(Year, Month, Day);
  2588.   CLTimeOfDay Tod(Hour, Minute, Second, MilliSecond);
  2589.  
  2590.   m_dSeconds = Date.GDN()*86400.0 +
  2591.          Tod.GetTotalSeconds() +
  2592.          Tod.GetMilliSecond()/1000.0;
  2593.  
  2594.   if (tf == LOCAL)
  2595.     CheckForValidLocalDate();
  2596.   return *this;
  2597. }
  2598.                     
  2599. CLDate& CLDate::Set(const SYSTEMTIME& st, TimeFrame tf, BOOL bUseDayOfWeek)
  2600. {
  2601.   if (bUseDayOfWeek)  //Using Day-in-month format
  2602.   {
  2603.     if (st.wYear)     //an absolute year, wDayOfWeek is 0 based
  2604.       Set(st.wYear, st.wMonth, st.wDay, (WORD)(st.wDayOfWeek+1), st.wHour, 
  2605.           st.wMinute, st.wSecond, st.wMilliseconds, tf);
  2606.     else              //use the current year
  2607.       Set(CurrentTime(tf).GetCDate().GetYear(), st.wMonth, st.wDay, 
  2608.           (WORD)(st.wDayOfWeek+1), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, tf);
  2609.   }
  2610.   else
  2611.   {
  2612.     if (st.wYear)     //an absolute year
  2613.       Set(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, tf);
  2614.     else              //use the current year
  2615.       Set(CurrentTime(tf).GetCDate().GetYear(), st.wMonth, st.wDay, 
  2616.           st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, tf);
  2617.   }
  2618.  
  2619.   return *this;
  2620. }
  2621.  
  2622.  
  2623. CLDate& CLDate::Set(LONG Year, WORD Month, WORD WeekOfMonth, 
  2624.                     WORD DayOfWeek, WORD Hour, WORD Minute, WORD Second,
  2625.                     WORD MilliSecond, TimeFrame tf)
  2626. {
  2627.   m_TimeFrame = tf;
  2628.  
  2629.   CDate Date(Year, Month, WeekOfMonth, DayOfWeek);
  2630.   CLTimeOfDay Tod(Hour, Minute, Second, MilliSecond);
  2631.  
  2632.   m_dSeconds = Date.GDN()*86400.0 +
  2633.          Tod.GetTotalSeconds() +
  2634.          Tod.GetMilliSecond()/1000.0;
  2635.  
  2636.   if (tf == LOCAL)
  2637.     CheckForValidLocalDate();
  2638.   return *this;
  2639. }
  2640.                     
  2641. CLDate& CLDate::Set(LONG Days, CDate::DateEpoch e, WORD Hour, WORD Minute,
  2642.                     WORD Second, WORD MilliSecond, TimeFrame tf)
  2643. {
  2644.   m_TimeFrame = tf;
  2645.  
  2646.   CDate Date(Days, e);
  2647.   CLTimeOfDay Tod(Hour, Minute, Second, MilliSecond);
  2648.  
  2649.   m_dSeconds = Date.GDN()*86400.0 +
  2650.          Tod.GetTotalSeconds() +
  2651.          Tod.GetMilliSecond()/1000.0;
  2652.  
  2653.   if (tf == LOCAL)
  2654.     CheckForValidLocalDate();
  2655.   return *this;
  2656. }
  2657.  
  2658. CLDate& CLDate::Set(const CTime& ct)
  2659. {
  2660.   m_TimeFrame = UTC;
  2661.   tm* pTM = ct.GetGmtTm();
  2662.   Set(pTM->tm_year + 1900, (WORD) (pTM->tm_mon+1), (WORD) pTM->tm_mday, 
  2663.          (WORD) pTM->tm_hour, (WORD) pTM->tm_min, (WORD) pTM->tm_sec, 0, UTC);
  2664.   return *this;  
  2665. }
  2666.  
  2667. CLDate& CLDate::Set(const CDate& Date, const CLTimeOfDay& Tod, TimeFrame tf)
  2668. {
  2669.   m_TimeFrame = tf;
  2670.  
  2671.   m_dSeconds = Date.GDN()*86400.0 +
  2672.          Tod.GetTotalSeconds() +
  2673.          Tod.GetMilliSecond()/1000.0;
  2674.  
  2675.  
  2676.   if (tf == LOCAL)
  2677.     CheckForValidLocalDate();
  2678.   return *this;  
  2679. }
  2680.       
  2681. #ifdef _WIN32
  2682. CLDate& CLDate::Set(const COleDateTime& oleTime, TimeFrame tf)
  2683. {
  2684.   return Set((LONG) oleTime.GetYear(), (WORD) oleTime.GetMonth(), (WORD) oleTime.GetDay(),
  2685.              (WORD) oleTime.GetHour(), (WORD) oleTime.GetMinute(), (WORD) oleTime.GetSecond(), 0, tf);
  2686. }                     
  2687. #endif
  2688.  
  2689. void CLDate::CheckForValidLocalDate()
  2690. {
  2691.   //Should only be called when tested a LOCAL CLDate
  2692.   ASSERT(m_TimeFrame == LOCAL);
  2693.  
  2694.   TIME_ZONE_INFORMATION tzi;
  2695.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  2696.   
  2697.   //Set the TimeFrame to UTC so that we do not need to perform DST conversions in
  2698.   //the following arithmetic
  2699.   m_TimeFrame = UTC;
  2700.  
  2701.   CLDate BeginDaylightTime;
  2702.   LONG ThisYear = GetCDate().GetYear();
  2703.   if (tzi.DaylightDate.wYear == 0)  //Using Day-in-month format
  2704.     BeginDaylightTime.Set(ThisYear, tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, (WORD)(tzi.DaylightDate.wDayOfWeek+1),
  2705.                           tzi.DaylightDate.wHour, tzi.DaylightDate.wMinute, tzi.DaylightDate.wSecond, tzi.DaylightDate.wMilliseconds, UTC);
  2706.   else
  2707.     BeginDaylightTime.Set(tzi.DaylightDate.wYear, tzi.DaylightDate.wMonth, tzi.DaylightDate.wDay, tzi.DaylightDate.wHour,
  2708.                           tzi.DaylightDate.wMinute, tzi.DaylightDate.wSecond, tzi.DaylightDate.wMilliseconds, UTC);
  2709.  
  2710.   CLDate BeginStandardTime;
  2711.   if (tzi.StandardDate.wYear == 0)  //Using Day-in-month format
  2712.     BeginStandardTime.Set(ThisYear, tzi.StandardDate.wMonth, tzi.StandardDate.wDay, (WORD)(tzi.StandardDate.wDayOfWeek+1),
  2713.                           tzi.StandardDate.wHour, tzi.StandardDate.wMinute, tzi.StandardDate.wSecond, tzi.StandardDate.wMilliseconds, UTC);
  2714.   else
  2715.     BeginStandardTime.Set(tzi.StandardDate.wYear, tzi.StandardDate.wMonth, tzi.StandardDate.wDay, tzi.StandardDate.wHour, 
  2716.                           tzi.StandardDate.wMinute, tzi.StandardDate.wSecond, tzi.StandardDate.wMilliseconds, UTC);
  2717.  
  2718.  
  2719. #ifdef _DEBUG
  2720.   CString& s = BeginDaylightTime.Format();
  2721.   s = BeginStandardTime.Format();
  2722. #endif
  2723.  
  2724.   if (tzi.DaylightBias > 0)
  2725.   {
  2726.     //A CLDate which specifies a date which occurs twice
  2727.     CLDate StartNonUnique(BeginDaylightTime - CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0, 0));
  2728.     if ((*this >= StartNonUnique) && (*this < BeginDaylightTime))
  2729.     {
  2730.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which represents a non unique absolute time\n"); 
  2731.       if (sm_bDoAsserts)
  2732.         ASSERT(FALSE);
  2733.       Set();
  2734.       return;
  2735.     }
  2736.  
  2737.     //A CLDate which specifies a date which does not occur
  2738.     CLDate EndSkip(BeginStandardTime + CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0, 0));
  2739.     if ((*this > BeginStandardTime) && (*this < EndSkip))
  2740.     {
  2741.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which does not occur\n");
  2742.       if (sm_bDoAsserts)
  2743.         ASSERT(FALSE);
  2744.       Set();
  2745.       return;
  2746.     }
  2747.  
  2748.   }
  2749.   else if (tzi.DaylightBias < 0)
  2750.   {
  2751.     //A CLDate which specifies a date which does not occur
  2752.     CLDate EndSkip(BeginDaylightTime + CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0, 0));
  2753.     if ((*this > BeginDaylightTime) && (*this < EndSkip))
  2754.     {
  2755.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which does not occur\n"); 
  2756.       if (sm_bDoAsserts)
  2757.         ASSERT(FALSE);
  2758.       Set();
  2759.       return;
  2760.     }
  2761.  
  2762.     //A CLDate which specifies a date which occurs twice
  2763.     CLDate StartNonUnique(BeginStandardTime - CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0, 0));
  2764.     if ((*this >= StartNonUnique) && 
  2765.         (*this <= BeginStandardTime) )
  2766.     {
  2767.       TRACE0("A CLDate using a LOCAL timeframe tried to be constructed which represents a non unique absolute time\n"); 
  2768.       if (sm_bDoAsserts)
  2769.         ASSERT(FALSE);
  2770.       Set();
  2771.       return;
  2772.     }
  2773.   }
  2774.  
  2775.   //return the timeframe back to local
  2776.   m_TimeFrame = LOCAL;
  2777. }
  2778.                     
  2779. CLDate CLDate::CurrentTime(TimeFrame tf)
  2780. {                                      
  2781.   #ifdef _WIN32
  2782.     SYSTEMTIME st;
  2783.     ::GetSystemTime(&st);
  2784.     CLDate rVal(st, UTC);
  2785.     rVal.SetTimeFrame(tf);
  2786.     return rVal; 
  2787.   #else         
  2788.     time_t csecs = time(NULL);
  2789.     tm* ct = localtime(&csecs);
  2790.     //Constructed using UTC timeframe to avoid check for valid timeframe
  2791.     CLDate rVal((LONG) (ct->tm_year+1900), (WORD) (ct->tm_mon+1), (WORD) (ct->tm_mday),
  2792.                 (WORD) (ct->tm_hour), (WORD) (ct->tm_min), (WORD) (ct->tm_sec), 0, UTC);
  2793.     rVal.m_TimeFrame = LOCAL;            
  2794.     rVal.SetTimeFrame(tf);
  2795.     return rVal;
  2796.   #endif
  2797. }
  2798.  
  2799. void CLDate::SetDefaultFormat(const CString& Format)
  2800. {
  2801.   sm_sDefaultFormat = Format;
  2802. }
  2803.  
  2804. CString& CLDate::GetDefaultFormat()
  2805. {
  2806.   return sm_sDefaultFormat;
  2807. }
  2808.  
  2809. CLTimeSpan CLDate::DeltaT(CLDate& d)
  2810. {
  2811.   CLTimeSpan Tspan(d - CLDate(CDate::Epoch2000(), CLTimeOfDay(0, 0, 0, 0), d.GetTimeFrame()));
  2812.   double T = Tspan.GetTotalDays()/36525.0;
  2813.   double S;
  2814.  
  2815.   double y = 2000 + T * 100;
  2816.   if (y > 2000)
  2817.     S = 102.3 + T * (123.5 + T * 32.5);
  2818.   else if (y < 1620)
  2819.   {
  2820.     if (y < 948)
  2821.       S = 2715.6 + T * (573.36 + T * 46.5);
  2822.     else 
  2823.       S = 50.6 + T * (67.5 + T * 22.5);
  2824.   }
  2825.   else /* Interpolate from the static data table */
  2826.   {
  2827.     int Index = (int)((y - 1620) / 2);
  2828.     if (Index > 185)
  2829.       Index = 185;
  2830.     y = y / 2 - Index - 810;
  2831.     S = (DeltaTTable[Index] + (DeltaTTable[Index + 1] - DeltaTTable[Index]) * y) / 10;
  2832.   }
  2833.  
  2834.   return CLTimeSpan(S);
  2835. }
  2836.  
  2837. BOOL CLDate::CurrentlyInDST()
  2838. {
  2839.   TIME_ZONE_INFORMATION tzi;
  2840.   return ::GetTimeZoneInformation(&tzi) == TIME_ZONE_ID_DAYLIGHT;
  2841. }
  2842.  
  2843. CLTimeSpan CLDate::DaylightBias()
  2844. {
  2845.   TIME_ZONE_INFORMATION tzi;
  2846.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  2847.  
  2848.   CLTimeSpan rVal;
  2849.   if (tzi.DaylightBias > 0)
  2850.     rVal = CLTimeSpan(0, 0, (WORD) tzi.DaylightBias, 0, 0);
  2851.   else
  2852.   {
  2853.     rVal = CLTimeSpan(0, 0, (WORD) -tzi.DaylightBias, 0, 0);
  2854.     rVal.Negate();
  2855.   }
  2856.   return rVal;
  2857. }
  2858.  
  2859. CLTimeSpan CLDate::TimezoneBias()
  2860. {
  2861.   TIME_ZONE_INFORMATION tzi;
  2862.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  2863.  
  2864.   CLTimeSpan rVal;
  2865.   LONG tzBias = tzi.StandardBias + tzi.Bias;
  2866.   if (tzBias > 0)
  2867.     rVal = CLTimeSpan(0, 0, (WORD) tzBias, 0, 0);
  2868.   else
  2869.   {
  2870.     rVal = CLTimeSpan(0, 0, (WORD) -tzBias, 0, 0);
  2871.     rVal.Negate();
  2872.   }
  2873.   return rVal;
  2874. }
  2875.  
  2876. CString& CLDate::DaylightName()
  2877. {
  2878.   TIME_ZONE_INFORMATION tzi;
  2879.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  2880.   CString sName(tzi.DaylightName);
  2881.   sm_sBuffer = sName;
  2882.   return sm_sBuffer;
  2883. }
  2884.  
  2885. CString& CLDate::StandardName()
  2886. {
  2887.   TIME_ZONE_INFORMATION tzi;
  2888.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  2889.   CString sName(tzi.StandardName);
  2890.   sm_sBuffer = sName;
  2891.   return sm_sBuffer;
  2892. }
  2893.  
  2894. #ifdef _DEBUG
  2895. BOOL CLDate::SetDoConstructorAsserts(BOOL bDoAsserts)
  2896. {
  2897.   BOOL bOldDoAsserts = sm_bDoAsserts;
  2898.   sm_bDoAsserts = bDoAsserts;
  2899.   return bOldDoAsserts;
  2900. }
  2901. #endif            
  2902.  
  2903. void CLDate::ClearStatics()
  2904. {
  2905.   sm_sBuffer.Empty();
  2906.   sm_sDefaultFormat.Empty();
  2907. }
  2908.  
  2909. CDate CLDate::GetCDate() const
  2910. {
  2911.   AssertValid();
  2912.   return CDate((LONG) (m_dSeconds/86400.0), CDate::EPOCH_GREG);
  2913. }
  2914.  
  2915. CLTimeOfDay CLDate::GetCLTimeOfDay() const
  2916. {
  2917.   AssertValid();
  2918.   return CLTimeOfDay(m_dSeconds - GetCDate().GDN()*86400.0);
  2919. }
  2920.  
  2921. DateLS CLDate::GetDate() const
  2922. {
  2923.   DateLS rVal;
  2924.   DateS ds = GetCDate().GetDate();
  2925.  
  2926.   rVal.lYear = ds.lYear; 
  2927.   rVal.wMonth = ds.wMonth;
  2928.   rVal.wDay = ds.wDay;
  2929.   rVal.wWday = ds.wWday;
  2930.   rVal.wYday = ds.wYday;
  2931.   rVal.ct = ds.ct;
  2932.   rVal.tf = m_TimeFrame;
  2933.   CLTimeOfDay tod(GetCLTimeOfDay());
  2934.   rVal.wHour = tod.GetHour();
  2935.   rVal.wMinute = tod.GetMinute();
  2936.   rVal.wSecond = tod.GetSecond();
  2937.   rVal.wMilliSeconds = tod.GetMilliSecond();
  2938.   
  2939.   return rVal;
  2940. };
  2941.  
  2942. SYSTEMTIME CLDate::GetSYSTEMTIME() const
  2943. {
  2944.   SYSTEMTIME s = GetCDate().GetSYSTEMTIME();
  2945.   CLTimeOfDay tod(GetCLTimeOfDay());
  2946.  
  2947.   s.wHour = tod.GetHour();
  2948.   s.wMinute = tod.GetMinute();
  2949.   s.wSecond = tod.GetSecond();
  2950.   s.wMilliseconds = tod.GetMilliSecond();
  2951.  
  2952.   return s;
  2953. }                         
  2954.  
  2955. tm CLDate::GetTM()
  2956. {
  2957.   AssertValid();
  2958.  
  2959.   tm rVal;                
  2960.   rVal.tm_sec   = 0;
  2961.   rVal.tm_min   = 0;
  2962.   rVal.tm_hour  = 0;
  2963.   rVal.tm_mday  = 0;
  2964.   rVal.tm_mon   = 0;
  2965.   rVal.tm_year  = 0;
  2966.   rVal.tm_wday  = 0;
  2967.   rVal.tm_yday  = 0;
  2968.   rVal.tm_isdst = 0;
  2969.  
  2970.   DateLS ds = GetDate();
  2971.  
  2972. #ifdef _WIN32
  2973.   long MinYear = 1900L + LONG_MIN;
  2974.   long MaxYear = LONG_MAX;
  2975. #else
  2976.   long MinYear = 1900L + SHRT_MIN;
  2977.   long MaxYear = 1900L + SHRT_MAX;
  2978. #endif
  2979.  
  2980.   //handle range errors
  2981.   if ((ds.lYear < MinYear) || (ds.lYear > MaxYear))
  2982.   {
  2983.     ASSERT(FALSE);
  2984.     return rVal;
  2985.   }
  2986.   
  2987.   rVal.tm_hour = ds.wHour;
  2988.   rVal.tm_min = ds.wMinute;
  2989.   rVal.tm_sec = ds.wSecond;
  2990.   rVal.tm_year = (int) (ds.lYear - 1900L);
  2991.   rVal.tm_mon = ds.wMonth - 1;  //tm struct uses 0 based indices
  2992.   rVal.tm_wday = ds.wWday - 1;  //tm struct uses 0 based indices
  2993.   rVal.tm_mday = ds.wDay;
  2994.   rVal.tm_wday = ds.wYday - 1; //Returns days since Jan 1
  2995.   rVal.tm_isdst = IsDST();
  2996.               
  2997.   return rVal;
  2998. }
  2999.  
  3000. TimeFrame CLDate::GetTimeFrame() const
  3001. {
  3002.   AssertValid();
  3003.   return m_TimeFrame;
  3004. }
  3005.  
  3006. TimeFrame CLDate::SetTimeFrame(TimeFrame tf)
  3007. {
  3008.   if (tf == m_TimeFrame)  //quick return
  3009.     return tf;
  3010.     
  3011.   TimeFrame OldTF = m_TimeFrame;   
  3012.  
  3013.   switch (m_TimeFrame)
  3014.   {
  3015.     case LOCAL:
  3016.     {
  3017.       switch (tf)
  3018.       {
  3019.         case UTC:
  3020.         {
  3021.           //pretend that timeframe is UTC to avoid recursion in the arithmetic
  3022.           m_TimeFrame = UTC;
  3023.  
  3024.           *this += TimezoneBias();
  3025.           if (DST())
  3026.             *this += DaylightBias();
  3027.           break;
  3028.         }
  3029.         case ET:
  3030.         {
  3031.           SetTimeFrame(UTC);
  3032.           SetTimeFrame(ET);
  3033.           break;
  3034.         }
  3035.         default: ASSERT(FALSE);
  3036.       }
  3037.       break;
  3038.     }
  3039.     case ET:
  3040.     {
  3041.       switch (tf)
  3042.       {
  3043.         case UTC:
  3044.         {
  3045.           *this -= DeltaT();
  3046.           break;
  3047.         }
  3048.         case LOCAL:
  3049.         {
  3050.           SetTimeFrame(UTC);
  3051.           SetTimeFrame(LOCAL);
  3052.           break;
  3053.         }
  3054.         default: ASSERT(FALSE);
  3055.       }
  3056.       break;
  3057.     }
  3058.     case UTC:
  3059.     {
  3060.       switch (tf)
  3061.       {
  3062.         case LOCAL:
  3063.         {
  3064.           *this -= TimezoneBias();
  3065.           if (DST())
  3066.           {
  3067.             *this -= DaylightBias();
  3068.             sm_bIsDst = TRUE;
  3069.           }
  3070.           else
  3071.             sm_bIsDst = FALSE;
  3072.           break;
  3073.         }
  3074.         case ET:
  3075.         {
  3076.           *this += DeltaT();
  3077.           break;
  3078.         }
  3079.         default: ASSERT(FALSE);
  3080.       }
  3081.       break;
  3082.     }
  3083.  
  3084.     default: ASSERT(FALSE);
  3085.   }
  3086.  
  3087.   m_TimeFrame = tf;
  3088.   return OldTF;
  3089. };
  3090.  
  3091. BOOL CLDate::IsDST()
  3092. {
  3093.   AssertValid();
  3094.   BOOL rVal;  
  3095.   TimeFrame OldTF = GetTimeFrame();
  3096.   if (OldTF != LOCAL)
  3097.   {
  3098.     SetTimeFrame(LOCAL);
  3099.     rVal = sm_bIsDst;
  3100.   }
  3101.   else
  3102.     rVal = DST();
  3103.   return rVal;
  3104. }
  3105.  
  3106. BOOL CLDate::DST()
  3107. {
  3108.   AssertValid();
  3109.   BOOL rVal = TRUE;
  3110.   TIME_ZONE_INFORMATION tzi;
  3111.   ASSERT(::GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_UNKNOWN);
  3112.  
  3113.   long lYear = GetCDate().GetYear();
  3114.  
  3115.   //SYSTEMTIME can only accomadate a WORD sized year
  3116.   //so we always return FALSE if outside of this range
  3117.   if ((lYear > SHRT_MAX) || (lYear < 0))
  3118.     rVal = FALSE;
  3119.  
  3120.   if (rVal)
  3121.   {
  3122.     TimeFrame OldTF = m_TimeFrame;
  3123.     m_TimeFrame = UTC;
  3124.  
  3125.     BOOL bUseDayOfWeek = FALSE;
  3126.     if (tzi.DaylightDate.wYear == 0)
  3127.     {
  3128.       bUseDayOfWeek = TRUE;
  3129.       tzi.DaylightDate.wYear = (WORD) lYear;
  3130.     }
  3131.  
  3132.     CLDate BeginDST(tzi.DaylightDate, UTC, bUseDayOfWeek);
  3133.  
  3134. #ifdef _DEBUG
  3135.     CString& s = BeginDST.Format();
  3136. #endif
  3137.  
  3138.     bUseDayOfWeek = FALSE;
  3139.     if (tzi.StandardDate.wYear == 0)
  3140.     {
  3141.       bUseDayOfWeek = TRUE;
  3142.       tzi.StandardDate.wYear = (WORD) lYear;
  3143.     }
  3144.  
  3145.     CLDate EndDST(tzi.StandardDate, UTC, bUseDayOfWeek);
  3146. #ifdef _DEBUG
  3147.     s = EndDST.Format();
  3148. #endif
  3149.   
  3150.     rVal = rVal && (*this >= BeginDST && *this < EndDST);
  3151.  
  3152.     m_TimeFrame = OldTF;
  3153.   }
  3154.   
  3155.   return rVal;
  3156. }
  3157.  
  3158. CString& CLDate::GetStringTimeFrame() const
  3159. {
  3160.   switch (m_TimeFrame)
  3161.   {
  3162.     case UTC:   
  3163.       if (!sm_sBuffer.LoadString(IDS_UTC))
  3164.         ASSERT(FALSE);
  3165.       break;
  3166.     case ET:  
  3167.       if (!sm_sBuffer.LoadString(IDS_ET))
  3168.         ASSERT(FALSE);
  3169.       break;
  3170.     case LOCAL: 
  3171.       if (!sm_sBuffer.LoadString(IDS_LOCAL))
  3172.         ASSERT(FALSE);
  3173.       break;
  3174.     default:  
  3175.       ASSERT(FALSE);
  3176.       break;
  3177.   }
  3178.   return sm_sBuffer;
  3179. }
  3180.  
  3181. double CLDate::GDNAsDouble() const
  3182. {
  3183.   AssertValid();
  3184.   return m_dSeconds/86400;
  3185. }
  3186.  
  3187. double CLDate::GSNAsDouble() const
  3188. {
  3189.   AssertValid();
  3190.   return m_dSeconds;
  3191. }
  3192.  
  3193.  
  3194. void CLDate::AddYear(int Years)
  3195. {
  3196.   AssertValid();
  3197.   CDate Date(GetCDate());
  3198.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3199.   Date.AddYear(Years);
  3200.   Set(Date, Tod, m_TimeFrame);
  3201. }
  3202.  
  3203. void CLDate::AddMonth(int Months)
  3204. {
  3205.   AssertValid();
  3206.   CDate Date(GetCDate());
  3207.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3208.   Date.AddMonth(Months);
  3209.   Set(Date, Tod, m_TimeFrame);
  3210. }
  3211.  
  3212. void CLDate::AddWeek(int Weeks)
  3213. {
  3214.   AssertValid();
  3215.  
  3216.   CDate Date(GetCDate());
  3217.   CLTimeOfDay Tod(GetCLTimeOfDay());
  3218.   Date.AddWeek(Weeks);
  3219.   Set(Date, Tod, m_TimeFrame);
  3220. }
  3221.  
  3222. BOOL CLDate::IsValid() const
  3223. {
  3224.   return (m_dSeconds != DBL_MAX);
  3225. }
  3226.  
  3227. CLTimeSpan CLDate::DeltaT()
  3228. {
  3229.   AssertValid();
  3230.   return DeltaT(*this);
  3231. }
  3232.  
  3233. CLDate& CLDate::operator=(const CLDate& d) 
  3234. {
  3235.   m_TimeFrame = d.m_TimeFrame;
  3236.   m_dSeconds = d.m_dSeconds;
  3237.  
  3238.   return *this;
  3239. }              
  3240.  
  3241. CLDate CLDate::operator+(const CLTimeSpan& TimeSpan)
  3242. {
  3243.   AssertValid();
  3244.   TimeSpan.AssertValid();
  3245.  
  3246.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3247.   TimeFrame OldTF = GetTimeFrame();
  3248.   if (GetTimeFrame() == LOCAL)
  3249.     SetTimeFrame(UTC);
  3250.  
  3251.  
  3252.   double s = m_dSeconds + TimeSpan.m_dSeconds;
  3253.   CLDate rVal;
  3254.   rVal.m_dSeconds = s;
  3255.   rVal.m_TimeFrame = m_TimeFrame;
  3256.  
  3257.   SetTimeFrame(OldTF);
  3258.   rVal.SetTimeFrame(OldTF);
  3259.  
  3260.   return rVal;
  3261. }
  3262.  
  3263. CLTimeSpan CLDate::operator-(CLDate& ld)
  3264. {
  3265.   AssertValid();
  3266.   ld.AssertValid();
  3267.  
  3268.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3269.   TimeFrame OldTF1 = GetTimeFrame();
  3270.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3271.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3272.   {
  3273.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3274.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3275.   }
  3276.  
  3277.  
  3278.   double s = m_dSeconds - ld.m_dSeconds;
  3279.   CLTimeSpan rVal(s);
  3280.  
  3281.   SetTimeFrame(OldTF1);
  3282.   ld.SetTimeFrame(OldTF2);
  3283.  
  3284.   return rVal;
  3285. }
  3286.  
  3287. CLDate CLDate::operator-(const CLTimeSpan& TimeSpan)
  3288. {
  3289.   AssertValid();
  3290.   TimeSpan.AssertValid();
  3291.  
  3292.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3293.   TimeFrame OldTF = GetTimeFrame();
  3294.   if (GetTimeFrame() == LOCAL)
  3295.     SetTimeFrame(UTC);
  3296.  
  3297.  
  3298.   double s = m_dSeconds - TimeSpan.m_dSeconds;
  3299.   CLDate rVal;
  3300.   rVal.m_dSeconds = s;
  3301.   rVal.m_TimeFrame = m_TimeFrame;
  3302.  
  3303.  
  3304.   return rVal;
  3305. }
  3306.  
  3307. CLDate& CLDate::operator+=(const CLTimeSpan& TimeSpan)
  3308. {
  3309.   *this = *this + TimeSpan;
  3310.   return *this;
  3311. }
  3312.  
  3313. CLDate& CLDate::operator-=(const CLTimeSpan& TimeSpan)
  3314. {
  3315.   *this = *this - TimeSpan;
  3316.   return *this;
  3317. }
  3318.  
  3319. CLDate& CLDate::operator++()
  3320. {
  3321.   AssertValid();
  3322.   m_dSeconds += 86400;
  3323.   return *this;
  3324. }
  3325.  
  3326. CLDate& CLDate::operator--()
  3327. {
  3328.   AssertValid();
  3329.   m_dSeconds -= 86400;
  3330.   return *this;
  3331. }
  3332.   
  3333. BOOL CLDate::operator==(CLDate& ld)
  3334. {
  3335.   AssertValid();
  3336.   
  3337.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3338.   TimeFrame OldTF1 = GetTimeFrame();
  3339.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3340.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3341.   {
  3342.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3343.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3344.   }
  3345.  
  3346.   BOOL rVal = (m_dSeconds == ld.m_dSeconds);
  3347.  
  3348.   SetTimeFrame(OldTF1);
  3349.   ld.SetTimeFrame(OldTF2);
  3350.  
  3351.   return rVal;
  3352. }
  3353.  
  3354. BOOL CLDate::operator>(CLDate& ld)
  3355. {
  3356.   AssertValid();
  3357.  
  3358.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3359.   TimeFrame OldTF1 = GetTimeFrame();
  3360.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3361.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3362.   {
  3363.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3364.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3365.   }
  3366.  
  3367.   BOOL rVal = (m_dSeconds > ld.m_dSeconds);
  3368.  
  3369.   SetTimeFrame(OldTF1);
  3370.   ld.SetTimeFrame(OldTF2);
  3371.  
  3372.   return rVal;
  3373. }
  3374.  
  3375. BOOL CLDate::operator>=(CLDate& ld)
  3376. {
  3377.   AssertValid();
  3378.  
  3379.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3380.   TimeFrame OldTF1 = GetTimeFrame();
  3381.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3382.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3383.   {
  3384.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3385.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3386.   }
  3387.  
  3388.   BOOL rVal = (m_dSeconds >= ld.m_dSeconds);
  3389.  
  3390.   SetTimeFrame(OldTF1);
  3391.   ld.SetTimeFrame(OldTF2);
  3392.  
  3393.   return rVal;
  3394. }
  3395.  
  3396. BOOL CLDate::operator<(CLDate& ld)
  3397. {
  3398.   AssertValid();
  3399.  
  3400.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3401.   TimeFrame OldTF1 = GetTimeFrame();
  3402.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3403.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3404.   {
  3405.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3406.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3407.   }
  3408.  
  3409.   BOOL rVal = (m_dSeconds < ld.m_dSeconds);
  3410.  
  3411.   SetTimeFrame(OldTF1);
  3412.   ld.SetTimeFrame(OldTF2);
  3413.  
  3414.   return rVal;
  3415. }
  3416.  
  3417. BOOL CLDate::operator<=(CLDate& ld)
  3418. {
  3419.   AssertValid();
  3420.  
  3421.   //Because LOCAL Time is not a continous timeframe convert if necessary
  3422.   TimeFrame OldTF1 = GetTimeFrame();
  3423.   TimeFrame OldTF2 = ld.GetTimeFrame();
  3424.   if (!((OldTF1 == ET) && (OldTF2 == ET)))
  3425.   {
  3426.     TimeFrame OldTF1 = SetTimeFrame(UTC);
  3427.     TimeFrame OldTF2 = ld.SetTimeFrame(UTC);
  3428.   }
  3429.  
  3430.   BOOL rVal = (m_dSeconds <= ld.m_dSeconds);
  3431.  
  3432.   SetTimeFrame(OldTF1);
  3433.   ld.SetTimeFrame(OldTF2);
  3434.  
  3435.   return rVal;
  3436. }
  3437.  
  3438. BOOL CLDate::operator!=(CLDate& ld)
  3439. {
  3440.   AssertValid();
  3441.   return !operator==(ld);
  3442. }
  3443.  
  3444. #ifdef _DEBUG
  3445. void CLDate::AssertValid() const       
  3446. {
  3447.   CObject::AssertValid();
  3448.   ASSERT(IsValid());
  3449. }
  3450. #endif
  3451.  
  3452. #ifdef _DEBUG
  3453. void CLDate::Dump(CDumpContext& dc) const
  3454. {
  3455.   CObject::Dump(dc);
  3456.   dc << Format() << _T("\n");
  3457. }
  3458. #endif           
  3459.  
  3460. /*
  3461. CString CLDate::Format(const CString& sFormat=CDate::m_sDefaultFormat) const
  3462. %a    Abbreviated weekday name
  3463. %A    Full weekday name
  3464. %b    Abbreviated month name
  3465. %B    Full month name
  3466. %d    Day of month as decimal number (01 - 31)
  3467. %j    Day of year as decimal number (001 - 366)
  3468. %m    Month as decimal number (01 - 12)
  3469. %P    AM / PM indicator
  3470. %U    Week of year as decimal number
  3471. %w    Weekday as decimal number (1 - 7; Sunday is 1)
  3472. %x    Date representation for current locale,  namely 
  3473.         Date representation + " " + Time Representation for current locale
  3474. %y    Year without century, as decimal number (00 - 99)
  3475. %Y    Year with century, as decimal number
  3476. %c    Year displayed using C.E.(Current Epoch) / B.C.E (Before Current Epoch) convention e.g. -1023 = 1022 BCE
  3477. %t    String containing a representation of the TimeFrame ("UTC", "LOCAL" or "ET")
  3478.  
  3479. %H    Hours in the day
  3480. %h    12 Hour format Hours in (00 - 12)
  3481. %M    Minutes in the hour
  3482. %S    Seconds in the minute
  3483. %F    MilliSeconds in the second
  3484. %%    Percent sign        
  3485.  
  3486.  
  3487. //may also need to include full windows escape character
  3488.  
  3489. %%    Percent sign
  3490.  
  3491. As in the printf function, the # flag may prefix any formatting code. 
  3492. In that case, the meaning of the format code is changed as follows.
  3493.  
  3494. Format Code Meaning
  3495. %#x Long date representation, appropriate to current locale, namely
  3496.       Long Date representation + " " + Time Representation for current locale
  3497.  
  3498.  
  3499. %#d, %#j, %#m, %#U, %#w, %#y, %#H, %#h, %#M, %#S  Remove leading zeros (if any).
  3500. */
  3501. CString& CLDate::Format(const CString& sFormat) const
  3502.   if (!IsValid())
  3503.     sm_sBuffer.Empty();
  3504.   else
  3505.   {
  3506.     CString sBuffer;
  3507.     sm_sBuffer.Empty();
  3508.     CString rVal;
  3509.     int sFmtLength = sFormat.GetLength();
  3510.  
  3511.     for (int i=0; i<sFmtLength; i++)
  3512.     {
  3513.       TCHAR c = sFormat.GetAt(i);
  3514.       if (c == '%')
  3515.       {
  3516.         ++i;
  3517.         if (i < sFmtLength)
  3518.         {
  3519.           c = sFormat.GetAt(i);
  3520.           switch (c)
  3521.           {
  3522.             case TCHAR('H'):
  3523.             {
  3524.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetHour());
  3525.               rVal += sBuffer;
  3526.               break;
  3527.             }
  3528.             case TCHAR('h'):
  3529.             {
  3530.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetAMPMHour());
  3531.               rVal += sBuffer;
  3532.               break;
  3533.             }
  3534.             case TCHAR('M'):
  3535.             {
  3536.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetMinute());
  3537.               rVal += sBuffer;
  3538.               break;
  3539.             }
  3540.             case TCHAR('P'):
  3541.             {
  3542.               rVal += GetCLTimeOfDay().GetAMPMString();
  3543.               break;
  3544.             }
  3545.             case TCHAR('S'):
  3546.             {
  3547.               sBuffer.Format(_T("%.02d"), GetCLTimeOfDay().GetSecond());
  3548.               rVal += sBuffer;
  3549.               break;
  3550.             }
  3551.             case TCHAR('F'):
  3552.             {
  3553.               sBuffer.Format(_T("%.03d"), GetCLTimeOfDay().GetMilliSecond());
  3554.               rVal += sBuffer;
  3555.               break;
  3556.             }
  3557.             case TCHAR('a'):
  3558.             {
  3559.               rVal += GetCDate().GetAbrStringDayOfWeek();
  3560.               break;
  3561.             }
  3562.             case TCHAR('A'):
  3563.             {
  3564.               rVal += GetCDate().GetFullStringDayOfWeek();
  3565.               break;
  3566.             }
  3567.             case TCHAR('b'):
  3568.             {
  3569.               rVal += GetCDate().GetAbrStringMonth();
  3570.               break;
  3571.             }
  3572.             case TCHAR('B'):
  3573.             {
  3574.               rVal += GetCDate().GetFullStringMonth();
  3575.               break;
  3576.             }
  3577.             case TCHAR('c'):
  3578.             {
  3579.               rVal += GetCDate().GetStringCEBCEYear();
  3580.               break;
  3581.             }
  3582.             case TCHAR('d'):
  3583.             {
  3584.               sBuffer.Format(_T("%.02d"), GetCDate().GetDay());
  3585.               rVal += sBuffer;
  3586.               break;
  3587.             }
  3588.             case TCHAR('j'):
  3589.             {
  3590.               sBuffer.Format(_T("%.03d"), GetCDate().DaysSinceJan0());
  3591.               rVal += sBuffer;
  3592.               break;
  3593.             }
  3594.             case TCHAR('m'):
  3595.             {
  3596.               sBuffer.Format(_T("%.02d"), GetCDate().GetMonth());
  3597.               rVal += sBuffer;
  3598.               break;
  3599.             }
  3600.             case TCHAR('t'):
  3601.             {
  3602.               rVal += GetStringTimeFrame();
  3603.               break;
  3604.             }
  3605.             case TCHAR('U'):
  3606.             {
  3607.               sBuffer.Format(_T("%.02d"), GetCDate().GetWeekOfYear());
  3608.               rVal += sBuffer;
  3609.               break;
  3610.             }
  3611.             case TCHAR('w'):
  3612.             {
  3613.               sBuffer.Format(_T("%d"), GetCDate().GetDayOfWeek());
  3614.               rVal += sBuffer;
  3615.               break;
  3616.             }
  3617.             case TCHAR('x'):
  3618.             {
  3619.               rVal += GetCDate().Format(_T("%x")) + _T(" ") + GetCLTimeOfDay().Format(_T("%x"));
  3620.               break;
  3621.             }
  3622.             case TCHAR('y'):
  3623.             {
  3624.               LONG Year = GetCDate().GetYear();
  3625.               sBuffer.Format(_T("%.02d"), GetCDate().Get2DigitYear());
  3626.               rVal += sBuffer;
  3627.               break;
  3628.             }
  3629.             case TCHAR('Y'):
  3630.             {
  3631.               sBuffer.Format(_T("%ld"), GetCDate().GetYear());
  3632.               rVal += sBuffer;
  3633.               break;
  3634.             }
  3635.             case TCHAR('#'):
  3636.             {
  3637.               if (i < sFmtLength)
  3638.               {
  3639.                 ++i;
  3640.                 c = sFormat.GetAt(i);
  3641.                 switch (c)
  3642.                 {
  3643.                   case TCHAR('d'):
  3644.                   {
  3645.                     sBuffer.Format(_T("%d"), GetCDate().GetDay());
  3646.                     rVal += sBuffer;
  3647.                     break;
  3648.                   }
  3649.                   case TCHAR('j'):
  3650.                   {
  3651.                     sBuffer.Format(_T("%d"), GetCDate().DaysSinceJan0());
  3652.                     rVal += sBuffer;
  3653.                     break;
  3654.                   }
  3655.                   case TCHAR('m'):
  3656.                   {
  3657.                     sBuffer.Format(_T("%d"), GetCDate().GetMonth());
  3658.                     rVal += sBuffer;
  3659.                     break;
  3660.                   }
  3661.                   case TCHAR('U'):
  3662.                   {
  3663.                     sBuffer.Format(_T("%d"), GetCDate().GetWeekOfYear());
  3664.                     rVal += sBuffer;
  3665.                     break;
  3666.                   }
  3667.                   case TCHAR('x'):
  3668.                   {
  3669.                     rVal += GetCDate().Format(_T("%#x")) + _T(" ") + GetCLTimeOfDay().Format(_T("%x"));
  3670.                     break;
  3671.                   }
  3672.                   case TCHAR('y'):
  3673.                   {
  3674.                     LONG Year = GetCDate().GetYear();
  3675.                     sBuffer.Format(_T("%d"), GetCDate().Get2DigitYear());
  3676.                     rVal += sBuffer;
  3677.                     break;
  3678.                   }
  3679.                   case TCHAR('H'):
  3680.                   {
  3681.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetHour());
  3682.                     rVal += sBuffer;
  3683.                     break;
  3684.                   }
  3685.                   case TCHAR('h'):
  3686.                   {
  3687.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetAMPMHour());
  3688.                     rVal += sBuffer;
  3689.                     break;
  3690.                   }
  3691.                   case TCHAR('M'):
  3692.                   {
  3693.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetMinute());
  3694.                     rVal += sBuffer;
  3695.                     break;
  3696.                   }
  3697.                   case TCHAR('S'):
  3698.                   {
  3699.                     sBuffer.Format(_T("%d"), GetCLTimeOfDay().GetSecond());
  3700.                     rVal += sBuffer;
  3701.                     break;
  3702.                   }
  3703.                   default:
  3704.                   {
  3705.                     rVal += c;
  3706.                     break;
  3707.                   }
  3708.                 }
  3709.               }
  3710.               break;
  3711.             }
  3712.             default:
  3713.             {
  3714.               rVal += c;
  3715.               break;
  3716.             }
  3717.           }
  3718.         }
  3719.       }
  3720.       else
  3721.       {
  3722.         rVal += c;
  3723.       }
  3724.     }
  3725.     sm_sBuffer = rVal;
  3726.   }
  3727.  
  3728.   return sm_sBuffer;
  3729. }
  3730.  
  3731. void CLDate::Serialize(CArchive& ar)
  3732. {
  3733.   CObject::Serialize(ar);
  3734.   if(ar.IsStoring())
  3735.   {
  3736.     ar << m_dSeconds;
  3737.     ar << (WORD) m_TimeFrame;
  3738.   }
  3739.   else
  3740.   {
  3741.     ar >> m_dSeconds;
  3742.     ar >> (WORD&) m_TimeFrame;
  3743.   }
  3744. }
  3745.  
  3746. ostream& operator<<(ostream& os, const CLDate& ld)
  3747. {
  3748.   return os << ld.Format();
  3749. }
  3750.  
  3751. CArchive& operator<<(CArchive& ar, CLDate& ld)
  3752. {
  3753.   ASSERT(ar.IsStoring());
  3754.   ld.Serialize(ar);
  3755.   return ar;
  3756. }
  3757.  
  3758. CArchive& operator>>(CArchive& ar, CLDate& ld)
  3759. {
  3760.   ASSERT(!ar.IsStoring());
  3761.   ld.Serialize(ar);
  3762.   return ar;
  3763. }
  3764.  
  3765.  
  3766.  
  3767.